Contract 0x55DA1CBD77B1c3b2d8Bfe0F5fDF63d684b49F8A5

 
 
Txn Hash
Method
Block
From
To
Value
0x1d8a4ee68213b71156957499f4ae8a50737da85755cf77b5177dfa5cbb5ed409Set New Admin133266342021-09-30 10:50:05483 days 22 hrs agoPaladin: Deployer IN  0x55da1cbd77b1c3b2d8bfe0f5fdf63d684b49f8a50 Ether0.00147519 52.10488629
0xc2fd02615a3e580ce52945ebbf4b56f11304ed0eb0eecfbc430235f605c2a7150x60806040133259202021-09-30 8:03:40484 days 1 hr agoPaladin: Deployer IN  Create: PalLoanToken0 Ether0.3446319 84.47326362
[ Download CSV Export 
Latest 1 internal transaction
Parent Txn Hash Block From To Value
0xc2fd02615a3e580ce52945ebbf4b56f11304ed0eb0eecfbc430235f605c2a715133259202021-09-30 8:03:40484 days 1 hr ago 0x55da1cbd77b1c3b2d8bfe0f5fdf63d684b49f8a5  Contract Creation0 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PalLoanToken

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 25000 runs

Other Settings:
default evmVersion
File 1 of 11 : PalLoanToken.sol
//██████╗  █████╗ ██╗      █████╗ ██████╗ ██╗███╗   ██╗
//██╔══██╗██╔══██╗██║     ██╔══██╗██╔══██╗██║████╗  ██║
//██████╔╝███████║██║     ███████║██║  ██║██║██╔██╗ ██║
//██╔═══╝ ██╔══██║██║     ██╔══██║██║  ██║██║██║╚██╗██║
//██║     ██║  ██║███████╗██║  ██║██████╔╝██║██║ ╚████║
//╚═╝     ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═════╝ ╚═╝╚═╝  ╚═══╝
                                                     

pragma solidity ^0.7.6;
pragma abicoder v2;
//SPDX-License-Identifier: MIT

import "./IPalLoanToken.sol";
import "./utils/ERC165.sol";
import "./utils/SafeMath.sol";
import "./utils/Strings.sol";
import "./utils/Admin.sol";
import "./IPaladinController.sol";
import "./BurnedPalLoanToken.sol";
import {Errors} from  "./utils/Errors.sol";

/** @title palLoanToken contract  */
/// @author Paladin
contract PalLoanToken is IPalLoanToken, ERC165, Admin {
    using SafeMath for uint;
    using Strings for uint;

    //Storage

    // Token name
    string public name;

    // Token symbol
    string public symbol;

    // Token base URI
    string public baseURI;

    //Incremental index for next token ID
    uint256 private index;

    uint256 public totalSupply;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private owners;

    // Mapping owner address to token count
    mapping(address => uint256) private balances;

    // Mapping from owner to list of owned token ID
    mapping(address => uint256[]) private ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private ownedTokensIndex;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private approvals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private operatorApprovals;

    // Paladin controller
    IPaladinController public controller;

    // Burned Token contract
    BurnedPalLoanToken public burnedToken;

    // Mapping from token ID to origin PalPool
    mapping(uint256 => address) private pools;

    // Mapping from token ID to PalLoan address
    mapping(uint256 => address) private loans;




    //Modifiers
    modifier controllerOnly() {
        //allows only the Controller and the admin to call the function
        require(msg.sender == admin || msg.sender == address(controller), Errors.CALLER_NOT_CONTROLLER);
        _;
    }

    modifier poolsOnly() {
        //allows only a PalPool listed in the Controller
        require(controller.isPalPool(msg.sender), Errors.CALLER_NOT_ALLOWED_POOL);
        _;
    }



    //Constructor
    constructor(address _controller, string memory _baseURI) {
        admin = msg.sender;

        // ERC721 parameters + storage data
        name = "PalLoan Token";
        symbol = "PLT";
        controller = IPaladinController(_controller);

        baseURI = _baseURI;

        //Create the Burned version of this ERC721
        burnedToken = new BurnedPalLoanToken("burnedPalLoan Token", "bPLT");
    }


    //Functions

    //Required ERC165 function
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            super.supportsInterface(interfaceId);
    }


    //URI method
    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        return string(abi.encodePacked(baseURI, tokenId.toString()));
    }


    /**
    * @notice Return the user balance (total number of token owned)
    * @param owner Address of the user
    * @return uint256 : number of token owned (in this contract only)
    */
    function balanceOf(address owner) external view override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return balances[owner];
    }


    /**
    * @notice Return owner of the token
    * @param tokenId Id of the token
    * @return address : owner address
    */
    function ownerOf(uint256 tokenId) public view override returns (address) {
        address owner = owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }


    /**
    * @notice Return the tokenId for a given owner and index
    * @param tokenIndex Index of the token
    * @return uint256 : tokenId
    */
    function tokenOfByIndex(address owner, uint256 tokenIndex) external view override returns (uint256) {
        require(tokenIndex < balances[owner], "ERC721: token query out of bonds");
        return ownedTokens[owner][tokenIndex];
    }


    /**
    * @notice Return owner of the token, even if the token was burned 
    * @dev Check if the given id has an owner in this contract, and then if it was burned and has an owner
    * @param tokenId Id of the token
    * @return address : address of the owner
    */
    function allOwnerOf(uint256 tokenId) external view override returns (address) {
        require(tokenId < index, "ERC721: owner query for nonexistent token");
        return owners[tokenId] != address(0) ? owners[tokenId] : burnedToken.ownerOf(tokenId);
    }


    /**
    * @notice Return the address of the palLoan for this token
    * @param tokenId Id of the token
    * @return address : address of the palLoan
    */
    function loanOf(uint256 tokenId) external view override returns(address){
        return loans[tokenId];
    }


    /**
    * @notice Return the palPool that issued this token
    * @param tokenId Id of the token
    * @return address : address of the palPool
    */
    function poolOf(uint256 tokenId) external view override returns(address){
        return pools[tokenId];
    }

    
    /**
    * @notice Return the list of all active palLoans owned by the user
    * @dev Find all the token owned by the user, and return the list of palLoans linked to the found tokens
    * @param owner User address
    * @return address[] : list of owned active palLoans
    */
    function loansOf(address owner) external view override returns(address[] memory){
        require(index > 0);
        uint256 tokenCount = balances[owner];
        address[] memory result = new address[](tokenCount);

        for(uint256 i = 0; i < tokenCount; i++){
            result[i] = loans[ownedTokens[owner][i]];
        }

        return result;
    }


    /**
    * @notice Return the list of all tokens owned by the user
    * @dev Find all the token owned by the user
    * @param owner User address
    * @return uint256[] : list of owned tokens
    */
    function tokensOf(address owner) external view override returns(uint256[] memory){
        require(index > 0);
        return ownedTokens[owner];
    }


    /**
    * @notice Return the list of all active palLoans owned by the user for the given palPool
    * @dev Find all the token owned by the user issued by the given Pool, and return the list of palLoans linked to the found tokens
    * @param owner User address
    * @return address[] : list of owned active palLoans for the given palPool
    */
    function loansOfForPool(address owner, address palPool) external view override returns(address[] memory){
        require(index > 0);
        uint j = 0;
        uint256 tokenCount = balances[owner];
        address[] memory result = new address[](tokenCount);

        for(uint256 i = 0; i < tokenCount; i++){
            if(pools[ownedTokens[owner][i]] == palPool){
                result[j] = loans[ownedTokens[owner][i]];
                j++;
            }
        }

        //put the result in a new array with correct size to avoid 0x00 addresses in the return array
        address[] memory filteredResult = new address[](j);
        for(uint256 k = 0; k < j; k++){
            filteredResult[k] = result[k];   
        }

        return filteredResult;
    }


    /**
    * @notice Return the list of all tokens owned by the user
    * @dev Find all the token owned by the user (in this contract and in the Burned contract)
    * @param owner User address
    * @return uint256[] : list of owned tokens
    */
    function allTokensOf(address owner) external view override returns(uint256[] memory){
        require(index > 0);
        uint256 tokenCount = balances[owner];
        uint256 totalCount = tokenCount.add(burnedToken.balanceOf(owner));
        uint256[] memory result = new uint256[](totalCount);

        uint256[] memory ownerTokens = ownedTokens[owner];
        for(uint256 i = 0; i < tokenCount; i++){
            result[i] = ownerTokens[i];
        }

        uint256[] memory burned = burnedToken.tokensOf(owner);
        for(uint256 j = tokenCount; j < totalCount; j++){
            result[j] = burned[j.sub(tokenCount)];
        }

        return result;
    }


    /**
    * @notice Return the list of all palLoans (active and closed) owned by the user
    * @dev Find all the token owned by the user, and all the burned tokens owned by the user,
    * and return the list of palLoans linked to the found tokens
    * @param owner User address
    * @return address[] : list of owned palLoans
    */
    function allLoansOf(address owner) external view override returns(address[] memory){
        require(index > 0);
        uint256 tokenCount = balances[owner];
        uint256 totalCount = tokenCount.add(burnedToken.balanceOf(owner));
        address[] memory result = new address[](totalCount);

        uint256[] memory ownerTokens = ownedTokens[owner];
        for(uint256 i = 0; i < tokenCount; i++){
            result[i] = loans[ownerTokens[i]];
        }

        uint256[] memory burned = burnedToken.tokensOf(owner);
        for(uint256 j = tokenCount; j < totalCount; j++){
            result[j] = loans[burned[j.sub(tokenCount)]];
        }

        return result;
    }


    /**
    * @notice Return the list of all palLoans owned by the user for the given palPool
    * @dev Find all the token owned by the user issued by the given Pool, and return the list of palLoans linked to the found tokens
    * @param owner User address
    * @return address[] : list of owned palLoans (active & closed) for the given palPool
    */
    function allLoansOfForPool(address owner, address palPool) external view override returns(address[] memory){
        require(index > 0);
        uint m = 0;
        uint256 tokenCount = balances[owner];
        uint256 totalCount = tokenCount.add(burnedToken.balanceOf(owner));
        address[] memory result = new address[](totalCount);

        uint256[] memory ownerTokens = ownedTokens[owner];
        for(uint256 i = 0; i < tokenCount; i++){
            if(pools[ownerTokens[i]] == palPool){
                result[m] = loans[ownerTokens[i]];
                m++;
            }
        }

        uint256[] memory burned = burnedToken.tokensOf(owner);
        for(uint256 j = tokenCount; j < totalCount; j++){
            uint256 burnedId = burned[j.sub(tokenCount)];
            if(pools[burnedId] == palPool){
                result[m] = loans[burnedId];
                m++;
            }
        }

        //put the result in a new array with correct size to avoid 0x00 addresses in the return array
        address[] memory filteredResult = new address[](m);
        for(uint256 k = 0; k < m; k++){
            filteredResult[k] = result[k];   
        }

        return filteredResult;
    }


    /**
    * @notice Check if the token was burned
    * @param tokenId Id of the token
    * @return bool : true if burned
    */
    function isBurned(uint256 tokenId) external view override returns(bool){
        return burnedToken.ownerOf(tokenId) != address(0);
    }





    /**
    * @notice Approve the address to spend the token
    * @param to Address of the spender
    * @param tokenId Id of the token to approve
    */
    function approve(address to, uint256 tokenId) external virtual override {
        address owner = ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            msg.sender == owner || isApprovedForAll(owner, msg.sender),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }


    /**
    * @notice Return the approved address for the token
    * @param tokenId Id of the token
    * @return address : spender's address
    */
    function getApproved(uint256 tokenId) public view override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return approvals[tokenId];
    }


    /**
    * @notice Give the operator approval on all tokens owned by the user, or remove it by setting it to false
    * @param operator Address of the operator to approve
    * @param approved Boolean : give or remove approval
    */
    function setApprovalForAll(address operator, bool approved) external virtual override {
        require(operator != msg.sender, "ERC721: approve to caller");

        operatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }


    /**
    * @notice Return true if the operator is approved for the given user
    * @param owner Amount of the owner
    * @param operator Address of the operator
    * @return bool :  result
    */
    function isApprovedForAll(address owner, address operator) public view override returns (bool) {
        return operatorApprovals[owner][operator];
    }







    /**
    * @notice Transfer the token from the owner to the recipient (if allowed)
    * @param from Address of the owner
    * @param to Address of the recipient
    * @param tokenId Id of the token
    */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external virtual override {
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }


    /**
    * @notice Safe transfer the token from the owner to the recipient (if allowed)
    * @param from Address of the owner
    * @param to Address of the recipient
    * @param tokenId Id of the token
    */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external virtual override {
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");
        require(_transfer(from, to, tokenId), "ERC721: transfer failed");
    }


    /**
    * @notice Safe transfer the token from the owner to the recipient (if allowed)
    * @param from Address of the owner
    * @param to Address of the recipient
    * @param tokenId Id of the token
    */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) external virtual override {
        _data;
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");
        require(_transfer(from, to, tokenId), "ERC721: transfer failed");
    }






    /**
    * @notice Mint a new token to the given address
    * @dev Mint the new token, and list it with the given palLoan and palPool
    * @param to Address of the user to mint the token to
    * @param palPool Address of the palPool issuing the token
    * @param palLoan Address of the palLoan linked to the token
    * @return uint256 : new token Id
    */
    function mint(address to, address palPool, address palLoan) external override poolsOnly returns(uint256){
        require(palLoan != address(0), Errors.ZERO_ADDRESS);

        //Call the internal mint method, and get the new token Id
        uint256 newId = _mint(to);

        //Set the correct data in mappings for this token
        loans[newId] = palLoan;
        pools[newId] = palPool;

        //Emit the Mint Event
        emit NewLoanToken(palPool, to, palLoan, newId);

        //Return the new token Id
        return newId;
    }


    /**
    * @notice Burn the given token
    * @dev Burn the token, and mint the BurnedToken for this token
    * @param tokenId Id of the token to burn
    * @return bool : success
    */
    function burn(uint256 tokenId) external override poolsOnly returns(bool){
        address owner = ownerOf(tokenId);

        require(owner != address(0), "ERC721: token nonexistant");

        //Mint the Burned version of this token
        burnedToken.mint(owner, tokenId);

        //Emit the correct event
        emit BurnLoanToken(pools[tokenId], owner, loans[tokenId], tokenId);

        //call the internal burn method
        return _burn(owner, tokenId);
    }

    

    



    /**
    * @notice Check if a token exists
    * @param tokenId Id of the token
    * @return bool : true if token exists (active or burned)
    */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return owners[tokenId] != address(0) || burnedToken.ownerOf(tokenId) != address(0);
    }


    /**
    * @notice Check if the given user is approved for the given token
    * @param spender Address of the user to check
    * @param tokenId Id of the token
    * @return bool : true if approved
    */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }


    function _addTokenToOwner(address to, uint tokenId) internal {
        uint ownerIndex = balances[to];
        ownedTokens[to].push(tokenId);
        ownedTokensIndex[tokenId] = ownerIndex;
        balances[to] = balances[to].add(1);
    }


    function _removeTokenToOwner(address from, uint tokenId) internal {
        // To prevent any gap in the array, we subsitute the last token with the one to remove, 
        // and pop the last element in the array
        uint256 lastTokenIndex = balances[from].sub(1);
        uint256 tokenIndex = ownedTokensIndex[tokenId];
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = ownedTokens[from][lastTokenIndex];
            ownedTokens[from][tokenIndex] = lastTokenId;
            ownedTokensIndex[lastTokenId] = tokenIndex;
        }
        delete ownedTokensIndex[tokenId];
        ownedTokens[from].pop();
        balances[from] = balances[from].sub(1);
    }


    /**
    * @notice Mint the new token
    * @param to Address of the user to mint the token to
    * @return uint : Id of the new token
    */
    function _mint(address to) internal virtual returns(uint) {
        require(to != address(0), "ERC721: mint to the zero address");

        //Get the new token Id, and increase the global index
        uint tokenId = index;
        index = index.add(1);
        totalSupply = totalSupply.add(1);

        //Write this token in the storage
        _addTokenToOwner(to, tokenId);
        owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        //Return the new token Id
        return tokenId;
    }


    /**
    * @notice Burn the given token
    * @param owner Address of the token owner
    * @param tokenId Id of the token to burn
    * @return bool : success
    */
    function _burn(address owner, uint256 tokenId) internal virtual returns(bool) {
        //Reset the token approval
        _approve(address(0), tokenId);

        //Update data in storage
        totalSupply = totalSupply.sub(1);
        _removeTokenToOwner(owner, tokenId);
        owners[tokenId] = address(0);

        emit Transfer(owner, address(0), tokenId);

        return true;
    }


    /**
    * @notice Transfer the token from the owner to the recipient
    * @dev Deposit underlying, and mints palToken for the user
    * @param from Address of the owner
    * @param to Address of the recipient
    * @param tokenId Id of the token
    * @return bool : success
    */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual returns(bool) {
        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        //Reset token approval
        _approve(address(0), tokenId);

        //Update storage data
        _removeTokenToOwner(from, tokenId);
        _addTokenToOwner(to, tokenId);
        owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        return true;
    }


    /**
    * @notice Approve the given address to spend the token
    * @param to Address to approve
    * @param tokenId Id of the token to approve
    */
    function _approve(address to, uint256 tokenId) internal virtual {
        approvals[tokenId] = to;
        emit Approval(ownerOf(tokenId), to, tokenId);
    }



    //Admin functions
    /**
    * @notice Set a new Controller
    * @dev Loads the new Controller for the Pool
    * @param  _newController address of the new Controller
    */
    function setNewController(address _newController) external override controllerOnly {
        controller = IPaladinController(_newController);
    }


    function setNewBaseURI(string memory _newBaseURI) external override adminOnly {
        baseURI = _newBaseURI;
    }

}

File 2 of 11 : IPalLoanToken.sol
//██████╗  █████╗ ██╗      █████╗ ██████╗ ██╗███╗   ██╗
//██╔══██╗██╔══██╗██║     ██╔══██╗██╔══██╗██║████╗  ██║
//██████╔╝███████║██║     ███████║██║  ██║██║██╔██╗ ██║
//██╔═══╝ ██╔══██║██║     ██╔══██║██║  ██║██║██║╚██╗██║
//██║     ██║  ██║███████╗██║  ██║██████╔╝██║██║ ╚████║
//╚═╝     ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═════╝ ╚═╝╚═╝  ╚═══╝
                                                     

pragma solidity ^0.7.6;
pragma abicoder v2;
//SPDX-License-Identifier: MIT

import "./utils/IERC721.sol";

/** @title palLoanToken Interface  */
/// @author Paladin
interface IPalLoanToken is IERC721 {

    //Events

    /** @notice Event when a new Loan Token is minted */
    event NewLoanToken(address palPool, address indexed owner, address indexed palLoan, uint256 indexed tokenId);
    /** @notice Event when a Loan Token is burned */
    event BurnLoanToken(address palPool, address indexed owner, address indexed palLoan, uint256 indexed tokenId);


    //Functions
    function mint(address to, address palPool, address palLoan) external returns(uint256);
    function burn(uint256 tokenId) external returns(bool);

    function tokenURI(uint256 tokenId) external view returns (string memory);

    function tokenOfByIndex(address owner, uint256 tokenIdex) external view returns (uint256);
    function loanOf(uint256 tokenId) external view returns(address);
    function poolOf(uint256 tokenId) external view returns(address);
    function loansOf(address owner) external view returns(address[] memory);
    function tokensOf(address owner) external view returns(uint256[] memory);
    function loansOfForPool(address owner, address palPool) external view returns(address[] memory);
    function allTokensOf(address owner) external view returns(uint256[] memory);
    function allLoansOf(address owner) external view returns(address[] memory);
    function allLoansOfForPool(address owner, address palPool) external view returns(address[] memory);
    function allOwnerOf(uint256 tokenId) external view returns(address);

    function isBurned(uint256 tokenId) external view returns(bool);

    //Admin functions
    function setNewController(address _newController) external;
    function setNewBaseURI(string memory _newBaseURI) external;

}

File 3 of 11 : ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.6;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 4 of 11 : SafeMath.sol
pragma solidity ^0.7.6;
//SPDX-License-Identifier: MIT

// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol
// Subject to the MIT license.

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting with custom message on overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, errorMessage);

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot underflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction underflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot underflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, errorMessage);

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers.
     * Reverts on division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers.
     * Reverts with custom message on division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

File 5 of 11 : Strings.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.6;

/**
 * @dev String operations.
 */
library Strings {
    /**
     * @dev Converts a `uint256` to its ASCII `string` representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        uint256 index = digits - 1;
        temp = value;
        while (temp != 0) {
            buffer[index--] = bytes1(uint8(48 + temp % 10));
            temp /= 10;
        }
        return string(buffer);
    }
}

File 6 of 11 : Admin.sol
pragma solidity ^0.7.6;
//SPDX-License-Identifier: MIT


/** @title Admin contract  */
/// @author Paladin
contract Admin {

    /** @notice (Admin) Event when the contract admin is updated */
    event NewAdmin(address oldAdmin, address newAdmin);

    /** @dev Admin address for this contract */
    address payable internal admin;
    
    modifier adminOnly() {
        //allows only the admin of this contract to call the function
        require(msg.sender == admin, '1');
        _;
    }

        /**
    * @notice Set a new Admin
    * @dev Changes the address for the admin parameter
    * @param _newAdmin address of the new Controller Admin
    */
    function setNewAdmin(address payable _newAdmin) external adminOnly {
        address _oldAdmin = admin;
        admin = _newAdmin;

        emit NewAdmin(_oldAdmin, _newAdmin);
    }
}

File 7 of 11 : IPaladinController.sol
//██████╗  █████╗ ██╗      █████╗ ██████╗ ██╗███╗   ██╗
//██╔══██╗██╔══██╗██║     ██╔══██╗██╔══██╗██║████╗  ██║
//██████╔╝███████║██║     ███████║██║  ██║██║██╔██╗ ██║
//██╔═══╝ ██╔══██║██║     ██╔══██║██║  ██║██║██║╚██╗██║
//██║     ██║  ██║███████╗██║  ██║██████╔╝██║██║ ╚████║
//╚═╝     ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═════╝ ╚═╝╚═╝  ╚═══╝
                                                     

pragma solidity ^0.7.6;
//SPDX-License-Identifier: MIT

/** @title Paladin Controller Interface  */
/// @author Paladin
interface IPaladinController {
    
    //Events

    /** @notice Event emitted when a new token & pool are added to the list */
    event NewPalPool(address palPool, address palToken);
    /** @notice Event emitted when a token & pool are removed from the list */
    event RemovePalPool(address palPool, address palToken);


    //Functions
    function isPalPool(address pool) external view returns(bool);
    function getPalTokens() external view returns(address[] memory);
    function getPalPools() external view returns(address[] memory);
    function setInitialPools(address[] memory palTokens, address[] memory palPools) external returns(bool);
    function addNewPool(address palToken, address palPool) external returns(bool);
    function removePool(address _palPool) external returns(bool);

    function withdrawPossible(address palPool, uint amount) external view returns(bool);
    function borrowPossible(address palPool, uint amount) external view returns(bool);

    function depositVerify(address palPool, address dest, uint amount) external view returns(bool);
    function withdrawVerify(address palPool, address dest, uint amount) external view returns(bool);
    function borrowVerify(address palPool, address borrower, address delegatee, uint amount, uint feesAmount, address loanAddress) external view returns(bool);
    function expandBorrowVerify(address palPool, address loanAddress, uint newFeesAmount) external view returns(bool);
    function closeBorrowVerify(address palPool, address borrower, address loanAddress) external view returns(bool);
    function killBorrowVerify(address palPool, address killer, address loanAddress) external view returns(bool);

    //Admin functions
    function setPoolsNewController(address _newController) external returns(bool);
    function withdrawFromPool(address _pool, uint _amount, address _recipient) external returns(bool);

}

File 8 of 11 : BurnedPalLoanToken.sol
//██████╗  █████╗ ██╗      █████╗ ██████╗ ██╗███╗   ██╗
//██╔══██╗██╔══██╗██║     ██╔══██╗██╔══██╗██║████╗  ██║
//██████╔╝███████║██║     ███████║██║  ██║██║██╔██╗ ██║
//██╔═══╝ ██╔══██║██║     ██╔══██║██║  ██║██║██║╚██╗██║
//██║     ██║  ██║███████╗██║  ██║██████╔╝██║██║ ╚████║
//╚═╝     ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═════╝ ╚═╝╚═╝  ╚═══╝
                                                     

pragma solidity ^0.7.6;
pragma abicoder v2;
//SPDX-License-Identifier: MIT

import {Errors} from  "./utils/Errors.sol";
import "./utils/SafeMath.sol";
import "./IPalLoanToken.sol";



/** @title BurnedPalLoanToken contract  */
/// @author Paladin
contract BurnedPalLoanToken{
    using SafeMath for uint;

    //Storage

    // Token name
    string public name;
    // Token symbol
    string public symbol;

    //Token Minter contract : PalLoanToken
    address public minter;

    uint256 public totalSupply;
    // Mapping from token ID to owner address
    mapping(uint256 => address) private owners;

    // Mapping owner address to token count
    mapping(address => uint256[]) private balances;


    //Modifiers
    modifier authorized() {
        //allows only the palLoanToken contract to call methds
        require(msg.sender == minter, Errors.CALLER_NOT_MINTER);
        _;
    }


    //Events

    /** @notice Event when a new token is minted */
    event NewBurnedLoanToken(address indexed to, uint256 indexed tokenId);


    //Constructor
    constructor(string memory _name, string memory _symbol) {
        //ERC721 parameters
        name = _name;
        symbol = _symbol;
        minter = msg.sender;
        totalSupply = 0;
    }



    //Functions


    //URI method
    function tokenURI(uint256 tokenId) public view returns (string memory) {
        return IPalLoanToken(minter).tokenURI(tokenId);
    }

    /**
    * @notice Return the user balance (total number of token owned)
    * @param owner Address of the user
    * @return uint256 : number of token owned (in this contract only)
    */
    function balanceOf(address owner) external view returns (uint256){
        require(owner != address(0), "ERC721: balance query for the zero address");
        return balances[owner].length;
    }


    /**
    * @notice Return owner of the token
    * @param tokenId Id of the token
    * @return address : owner address
    */
    function ownerOf(uint256 tokenId) external view returns (address){
        return owners[tokenId];
    }

    
    /**
    * @notice Return the list of all tokens owned by the user
    * @dev Return the list of user's tokens
    * @param owner User address
    * @return uint256[] : list of owned tokens
    */
    function tokensOf(address owner) external view returns(uint256[] memory){
        return balances[owner];
    }

    

    /**
    * @notice Mint a new token to the given address with the given Id
    * @dev Mint the new token with the correct Id (from the previous burned token)
    * @param to Address of the user to mint the token to
    * @param tokenId Id of the token to mint
    * @return bool : success
    */
    function mint(address to, uint256 tokenId) external authorized returns(bool){
        require(to != address(0), "ERC721: mint to the zero address");

        //Update Supply
        totalSupply = totalSupply.add(1);

        //Add the new token to storage
        balances[to].push(tokenId);
        owners[tokenId] = to;

        //Emit the correct Event
        emit NewBurnedLoanToken(to, tokenId);

        return true;
    }


}

File 9 of 11 : Errors.sol
//██████╗  █████╗ ██╗      █████╗ ██████╗ ██╗███╗   ██╗
//██╔══██╗██╔══██╗██║     ██╔══██╗██╔══██╗██║████╗  ██║
//██████╔╝███████║██║     ███████║██║  ██║██║██╔██╗ ██║
//██╔═══╝ ██╔══██║██║     ██╔══██║██║  ██║██║██║╚██╗██║
//██║     ██║  ██║███████╗██║  ██║██████╔╝██║██║ ╚████║
//╚═╝     ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═════╝ ╚═╝╚═╝  ╚═══╝
                                                     

pragma solidity ^0.7.6;
//SPDX-License-Identifier: MIT

library Errors {
    // Admin error
    string public constant CALLER_NOT_ADMIN = '1'; // 'The caller must be the admin'
    string public constant CALLER_NOT_CONTROLLER = '29'; // 'The caller must be the admin or the controller'
    string public constant CALLER_NOT_ALLOWED_POOL = '30';  // 'The caller must be a palPool listed in the controller'
    string public constant CALLER_NOT_MINTER = '31';

    // ERC20 type errors
    string public constant FAIL_TRANSFER = '2';
    string public constant FAIL_TRANSFER_FROM = '3';
    string public constant BALANCE_TOO_LOW = '4';
    string public constant ALLOWANCE_TOO_LOW = '5';
    string public constant SELF_TRANSFER = '6';

    // PalPool errors
    string public constant INSUFFICIENT_CASH = '9';
    string public constant INSUFFICIENT_BALANCE = '10';
    string public constant FAIL_DEPOSIT = '11';
    string public constant FAIL_LOAN_INITIATE = '12';
    string public constant FAIL_BORROW = '13';
    string public constant ZERO_BORROW = '27';
    string public constant BORROW_INSUFFICIENT_FEES = '23';
    string public constant LOAN_CLOSED = '14';
    string public constant NOT_LOAN_OWNER = '15';
    string public constant LOAN_OWNER = '16';
    string public constant FAIL_LOAN_EXPAND = '17';
    string public constant NOT_KILLABLE = '18';
    string public constant RESERVE_FUNDS_INSUFFICIENT = '19';
    string public constant FAIL_MINT = '20';
    string public constant FAIL_BURN = '21';
    string public constant FAIL_WITHDRAW = '24';
    string public constant FAIL_CLOSE_BORROW = '25';
    string public constant FAIL_KILL_BORROW = '26';
    string public constant ZERO_ADDRESS = '22';
    string public constant INVALID_PARAMETERS = '28'; 
    string public constant FAIL_LOAN_DELEGATEE_CHANGE = '32';
    string public constant FAIL_LOAN_TOKEN_BURN = '33';
    string public constant FEES_ACCRUED_INSUFFICIENT = '34';

}

File 10 of 11 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.6;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

File 11 of 11 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.6;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 25000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_controller","type":"address"},{"internalType":"string","name":"_baseURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"palPool","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"palLoan","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"BurnLoanToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"palPool","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"palLoan","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NewLoanToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"allLoansOf","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"palPool","type":"address"}],"name":"allLoansOfForPool","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"allOwnerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"allTokensOf","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnedToken","outputs":[{"internalType":"contract BurnedPalLoanToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IPaladinController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isBurned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"loanOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"loansOf","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"palPool","type":"address"}],"name":"loansOfForPool","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"palPool","type":"address"},{"internalType":"address","name":"palLoan","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"poolOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newAdmin","type":"address"}],"name":"setNewAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"setNewBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newController","type":"address"}],"name":"setNewController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"tokenIndex","type":"uint256"}],"name":"tokenOfByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOf","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162004a0a38038062004a0a8339810160408190526200003491620001f5565b600080546001600160a01b0319163317905560408051808201909152600d8082526c2830b62637b0b7102a37b5b2b760991b60209092019182526200007c916001916200013b565b506040805180820190915260038082526214131560ea1b6020909201918252620000a9916002916200013b565b50600c80546001600160a01b0319166001600160a01b0384161790558051620000da9060039060208401906200013b565b50604051620000e990620001d0565b620000f490620002d7565b604051809103906000f08015801562000111573d6000803e3d6000fd5b50600d80546001600160a01b0319166001600160a01b0392909216919091179055506200032a9050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620001735760008555620001be565b82601f106200018e57805160ff1916838001178555620001be565b82800160010185558215620001be579182015b82811115620001be578251825591602001919060010190620001a1565b50620001cc929150620001de565b5090565b610bdd8062003e2d83390190565b5b80821115620001cc5760008155600101620001df565b6000806040838503121562000208578182fd5b82516001600160a01b03811681146200021f578283fd5b602084810151919350906001600160401b03808211156200023e578384fd5b818601915086601f83011262000252578384fd5b8151818111156200025f57fe5b604051601f8201601f19168101850183811182821017156200027d57fe5b604052818152838201850189101562000294578586fd5b8592505b81831015620002b7578383018501518184018601529184019162000298565b81831115620002c857858583830101525b80955050505050509250929050565b60408082526013908201527f6275726e656450616c4c6f616e20546f6b656e000000000000000000000000006060820152608060208201819052600490820152631894131560e21b60a082015260c00190565b613af3806200033a6000396000f3fe608060405234801561001057600080fd5b506004361061020b5760003560e01c80636a2291651161012a578063a22cb465116100bd578063db44fe071161008c578063e985e9c511610071578063e985e9c51461046c578063f4a6aff61461047f578063f77c4791146104925761020b565b8063db44fe0714610446578063e4ba13c7146104595761020b565b8063a22cb465146103fa578063b88d4fde1461040d578063c87b56dd14610420578063d9f00759146104335761020b565b80638d762211116100f95780638d762211146103b95780638eec99c8146103cc57806393a2b98b146103df57806395d89b41146103f25761020b565b80636a229165146103785780636c0360eb1461038b57806370a082311461039357806383966021146103a65761020b565b8063330c4ce0116101a25780635a3f2672116101715780635a3f2672146103125780635a7079241461033257806363185c42146103525780636352211e146103655761020b565b8063330c4ce0146102d157806342842e0e146102d957806342966c68146102ec57806359baef40146102ff5761020b565b806318160ddd116101de57806318160ddd146102835780631cb1ac0b1461029857806323b872dd146102ab5780632d7254e5146102be5761020b565b806301ffc9a71461021057806306fdde0314610239578063081812fc1461024e578063095ea7b31461026e575b600080fd5b61022361021e3660046132f6565b61049a565b6040516102309190613524565b60405180910390f35b6102416104f8565b604051610230919061352f565b61026161025c36600461337c565b6105a3565b604051610230919061344b565b61028161027c36600461320e565b610616565b005b61028b6106f7565b6040516102309190613a31565b6102816102a6366004613336565b6106fd565b6102816102b9366004613124565b61079a565b6102616102cc36600461337c565b6107eb565b610261610925565b6102816102e7366004613124565b610941565b6102236102fa36600461337c565b6109c2565b61028161030d36600461306a565b610c60565b61032561032036600461306a565b610d53565b60405161023091906134ec565b61034561034036600461306a565b610ddb565b6040516102309190613492565b61028b6103603660046130da565b610f13565b61026161037336600461337c565b611169565b6103456103863660046130a2565b6111c5565b61024161168e565b61028b6103a136600461306a565b611707565b6102616103b436600461337c565b61177f565b6103456103c73660046130a2565b6117a7565b6102816103da36600461306a565b611a25565b6103256103ed36600461306a565b611b33565b610241611dc9565b6102816104083660046131e1565b611e3f565b61028161041b366004613164565b611f29565b61024161042e36600461337c565b611faa565b61028b61044136600461320e565b61201d565b61022361045436600461337c565b6120bf565b61026161046736600461337c565b612188565b61022361047a3660046130a2565b6121b0565b61034561048d36600461306a565b6121eb565b61026161250f565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806104f057506104f08261252b565b90505b919050565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561059b5780601f106105705761010080835404028352916020019161059b565b820191906000526020600020905b81548152906001019060200180831161057e57829003601f168201915b505050505081565b60006105ae82612575565b6105ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e49061382b565b60405180910390fd5b506000908152600a602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b600061062182611169565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610689576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e490613942565b3373ffffffffffffffffffffffffffffffffffffffff821614806106b257506106b281336121b0565b6106e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4906136df565b6106f283836125f9565b505050565b60055481565b60005473ffffffffffffffffffffffffffffffffffffffff16331461078357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b8051610796906003906020840190612f59565b5050565b6107a43382612699565b6107da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e49061399f565b6107e583838361276c565b50505050565b60006004548210610828576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e490613799565b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff166108fc57600d546040517f6352211e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690636352211e906108a7908590600401613a31565b60206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f79190613086565b6104f0565b5060009081526006602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b600d5473ffffffffffffffffffffffffffffffffffffffff1681565b61094b3382612699565b610981576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e49061399f565b61098c83838361276c565b6106f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e490613580565b600c546040517f48f105ef00000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff16906348f105ef90610a1990339060040161344b565b60206040518083038186803b158015610a3157600080fd5b505afa158015610a45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6991906132da565b6040518060400160405280600281526020017f333000000000000000000000000000000000000000000000000000000000000081525090610ad7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4919061352f565b506000610ae383611169565b905073ffffffffffffffffffffffffffffffffffffffff8116610b32576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4906135b7565b600d546040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906340c10f1990610b8a908490879060040161346c565b602060405180830381600087803b158015610ba457600080fd5b505af1158015610bb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdc91906132da565b506000838152600f6020908152604080832054600e90925291829020549151859273ffffffffffffffffffffffffffffffffffffffff92831692858116927fd5a2cc9b5d51584c54c7ef6a352776654c4002f4e4bed8bc98c790385f3d360392610c4792169061344b565b60405180910390a4610c5981846128cd565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610c9d5750600c5473ffffffffffffffffffffffffffffffffffffffff1633145b6040518060400160405280600281526020017f323900000000000000000000000000000000000000000000000000000000000081525090610d0b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4919061352f565b50600c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6060600060045411610d6457600080fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602090815260409182902080548351818402810184019094528084529091830182828015610dcf57602002820191906000526020600020905b815481526020019060010190808311610dbb575b50505050509050919050565b6060600060045411610dec57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260076020526040812054908167ffffffffffffffff81118015610e2a57600080fd5b50604051908082528060200260200182016040528015610e54578160200160208202803683370190505b50905060005b82811015610f0b5773ffffffffffffffffffffffffffffffffffffffff851660009081526008602052604081208054600f92919084908110610e9857fe5b9060005260206000200154815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828281518110610ede57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101610e5a565b509392505050565b600c546040517f48f105ef00000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff16906348f105ef90610f6a90339060040161344b565b60206040518083038186803b158015610f8257600080fd5b505afa158015610f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fba91906132da565b6040518060400160405280600281526020017f333000000000000000000000000000000000000000000000000000000000000081525090611028576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4919061352f565b5060408051808201909152600281527f3232000000000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff83166110ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4919061352f565b5060006110b785612974565b6000818152600f60209081526040808320805473ffffffffffffffffffffffffffffffffffffffff808a167fffffffffffffffffffffffff00000000000000000000000000000000000000009283168117909355600e9094529382902080548a8516951694909417909355519293508392908816907fdd96885390f786440495509153d998abb30de89f8aaf3f907cfc4d2d3c60abab9061115990899061344b565b60405180910390a4949350505050565b60008181526006602052604081205473ffffffffffffffffffffffffffffffffffffffff16806104f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e490613799565b60606000600454116111d657600080fd5b73ffffffffffffffffffffffffffffffffffffffff80841660009081526007602052604080822054600d5491517f70a0823100000000000000000000000000000000000000000000000000000000815292939092849261129d9216906370a0823190611246908a9060040161344b565b60206040518083038186803b15801561125e57600080fd5b505afa158015611272573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112969190613394565b8390612a6f565b905060008167ffffffffffffffff811180156112b857600080fd5b506040519080825280602002602001820160405280156112e2578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff881660009081526008602090815260408083208054825181850281018501909352808352949550929390929183018282801561135357602002820191906000526020600020905b81548152602001906001019080831161133f575b5050505050905060005b8481101561144a578773ffffffffffffffffffffffffffffffffffffffff16600e600084848151811061138c57fe5b60209081029190910181015182528101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff16141561144257600f60008383815181106113d357fe5b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683878151811061141657fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526001909501945b60010161135d565b50600d546040517f5a3f267200000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff1690635a3f2672906114a2908c9060040161344b565b60006040518083038186803b1580156114ba57600080fd5b505afa1580156114ce573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115149190810190613239565b9050845b848110156115e15760008261152d8389612ae3565b8151811061153757fe5b6020908102919091018101516000818152600e90925260409091205490915073ffffffffffffffffffffffffffffffffffffffff8b8116911614156115d8576000818152600f6020526040902054855173ffffffffffffffffffffffffffffffffffffffff9091169086908a9081106115ac57fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526001909701965b50600101611518565b5060008667ffffffffffffffff811180156115fb57600080fd5b50604051908082528060200260200182016040528015611625578160200160208202803683370190505b50905060005b878110156116805784818151811061163f57fe5b602002602001015182828151811061165357fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161162b565b509998505050505050505050565b6003805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561059b5780601f106105705761010080835404028352916020019161059b565b600073ffffffffffffffffffffffffffffffffffffffff8216611756576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e49061373c565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526007602052604090205490565b6000908152600e602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60606000600454116117b857600080fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260076020526040812054818167ffffffffffffffff811180156117f657600080fd5b50604051908082528060200260200182016040528015611820578160200160208202803683370190505b50905060005b8281101561197b578573ffffffffffffffffffffffffffffffffffffffff16600e6000600860008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020848154811061189357fe5b6000918252602080832090910154835282019290925260400190205473ffffffffffffffffffffffffffffffffffffffff1614156119735773ffffffffffffffffffffffffffffffffffffffff871660009081526008602052604081208054600f9291908490811061190157fe5b9060005260206000200154815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682858151811061194757fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526001909301925b600101611826565b5060008367ffffffffffffffff8111801561199557600080fd5b506040519080825280602002602001820160405280156119bf578160200160208202803683370190505b50905060005b84811015611a1a578281815181106119d957fe5b60200260200101518282815181106119ed57fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526001016119c5565b509695505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611aab57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f3100000000000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040805191909216808252602082019390935281517ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc929181900390910190a15050565b6060600060045411611b4457600080fd5b73ffffffffffffffffffffffffffffffffffffffff80831660009081526007602052604080822054600d5491517f70a082310000000000000000000000000000000000000000000000000000000081529093611bb09216906370a082319061124690889060040161344b565b905060008167ffffffffffffffff81118015611bcb57600080fd5b50604051908082528060200260200182016040528015611bf5578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff8616600090815260086020908152604080832080548251818502810185019093528083529495509293909291830182828015611c6657602002820191906000526020600020905b815481526020019060010190808311611c52575b5050505050905060005b84811015611cab57818181518110611c8457fe5b6020026020010151838281518110611c9857fe5b6020908102919091010152600101611c70565b50600d546040517f5a3f267200000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff1690635a3f267290611d03908a9060040161344b565b60006040518083038186803b158015611d1b57600080fd5b505afa158015611d2f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611d759190810190613239565b9050845b84811015611dbd5781611d8c8288612ae3565b81518110611d9657fe5b6020026020010151848281518110611daa57fe5b6020908102919091010152600101611d79565b50919695505050505050565b600280546040805160206001841615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01909316849004601f8101849004840282018401909252818152929183018282801561059b5780601f106105705761010080835404028352916020019161059b565b73ffffffffffffffffffffffffffffffffffffffff8216331415611e8f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e49061364b565b336000818152600b6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871680855292529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151517905590519091907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3190611f1d908590613524565b60405180910390a35050565b611f333383612699565b611f69576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e49061399f565b611f7484848461276c565b6107e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e490613580565b6060611fb582612575565b611feb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4906138e5565b6003611ff683612b25565b6040516020016120079291906133ac565b6040516020818303038152906040529050919050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260076020526040812054821061207b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4906139fc565b73ffffffffffffffffffffffffffffffffffffffff831660009081526008602052604090208054839081106120ac57fe5b9060005260206000200154905092915050565b600d546040517f6352211e000000000000000000000000000000000000000000000000000000008152600091829173ffffffffffffffffffffffffffffffffffffffff90911690636352211e9061211a908690600401613a31565b60206040518083038186803b15801561213257600080fd5b505afa158015612146573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216a9190613086565b73ffffffffffffffffffffffffffffffffffffffff16141592915050565b6000908152600f602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600b6020908152604080832093909416825291909152205460ff1690565b60606000600454116121fc57600080fd5b73ffffffffffffffffffffffffffffffffffffffff80831660009081526007602052604080822054600d5491517f70a0823100000000000000000000000000000000000000000000000000000000815290936122689216906370a082319061124690889060040161344b565b905060008167ffffffffffffffff8111801561228357600080fd5b506040519080825280602002602001820160405280156122ad578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff861660009081526008602090815260408083208054825181850281018501909352808352949550929390929183018282801561231e57602002820191906000526020600020905b81548152602001906001019080831161230a575b5050505050905060005b848110156123b057600f600083838151811061234057fe5b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683828151811061238357fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101612328565b50600d546040517f5a3f267200000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff1690635a3f267290612408908a9060040161344b565b60006040518083038186803b15801561242057600080fd5b505afa158015612434573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261247a9190810190613239565b9050845b84811015611dbd57600f600083612495848a612ae3565b8151811061249f57fe5b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168482815181106124e257fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161247e565b600c5473ffffffffffffffffffffffffffffffffffffffff1681565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f01ffc9a70000000000000000000000000000000000000000000000000000000014919050565b60008181526006602052604081205473ffffffffffffffffffffffffffffffffffffffff161515806104f05750600d546040517f6352211e00000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff1690636352211e9061211a908690600401613a31565b6000818152600a6020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155819061265382611169565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006126a482612575565b6126da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e490613682565b60006126e583611169565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061275457508373ffffffffffffffffffffffffffffffffffffffff1661273c846105a3565b73ffffffffffffffffffffffffffffffffffffffff16145b80612764575061276481856121b0565b949350505050565b60008373ffffffffffffffffffffffffffffffffffffffff1661278e83611169565b73ffffffffffffffffffffffffffffffffffffffff16146127db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e490613888565b73ffffffffffffffffffffffffffffffffffffffff8316612828576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4906135ee565b6128336000836125f9565b61283d8483612c52565b6128478383612e17565b60008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a45060019392505050565b60006128da6000836125f9565b6005546128e8906001612ae3565b6005556128f58383612c52565b60008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555183919073ffffffffffffffffffffffffffffffffffffffff8616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a450600192915050565b600073ffffffffffffffffffffffffffffffffffffffff82166129c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e4906137f6565b6004546129d1816001612a6f565b6004556005546129e2906001612a6f565b6005556129ef8382612e17565b60008181526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a492915050565b600082820183811015610c5957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000610c5983836040518060400160405280601f81526020017f536166654d6174683a207375627472616374696f6e20756e646572666c6f7700815250612ea8565b606081612b66575060408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201526104f3565b8160005b8115612b7e57600101600a82049150612b6a565b60008167ffffffffffffffff81118015612b9757600080fd5b506040519080825280601f01601f191660200182016040528015612bc2576020820181803683370190505b5085935090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82015b8315612c4957600a840660300160f81b82828060019003935081518110612c0f57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84049350612bec565b50949350505050565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260076020526040812054612c83906001612ae3565b600083815260096020526040902054909150808214612d455773ffffffffffffffffffffffffffffffffffffffff84166000908152600860205260408120805484908110612ccd57fe5b9060005260206000200154905080600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110612d2557fe5b600091825260208083209091019290925591825260099052604090208190555b600083815260096020908152604080832083905573ffffffffffffffffffffffffffffffffffffffff8716835260089091529020805480612d8257fe5b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810183905590920190925573ffffffffffffffffffffffffffffffffffffffff86168252600790526040902054612de8906001612ae3565b73ffffffffffffffffffffffffffffffffffffffff909416600090815260076020526040902093909355505050565b73ffffffffffffffffffffffffffffffffffffffff821660008181526007602081815260408084208054600884528286208054600181810183559188528588200189905588875260098552928620819055959094529190529054612e7a91612a6f565b73ffffffffffffffffffffffffffffffffffffffff9093166000908152600760205260409020929092555050565b60008184841115612f51576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612f16578181015183820152602001612efe565b50505050905090810190601f168015612f435780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282612f8f5760008555612fd5565b82601f10612fa857805160ff1916838001178555612fd5565b82800160010185558215612fd5579182015b82811115612fd5578251825591602001919060010190612fba565b50612fe1929150612fe5565b5090565b5b80821115612fe15760008155600101612fe6565b600067ffffffffffffffff83111561300e57fe5b61303f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601613a3a565b905082815283838301111561305357600080fd5b828260208301376000602084830101529392505050565b60006020828403121561307b578081fd5b8135610c5981613a8a565b600060208284031215613097578081fd5b8151610c5981613a8a565b600080604083850312156130b4578081fd5b82356130bf81613a8a565b915060208301356130cf81613a8a565b809150509250929050565b6000806000606084860312156130ee578081fd5b83356130f981613a8a565b9250602084013561310981613a8a565b9150604084013561311981613a8a565b809150509250925092565b600080600060608486031215613138578283fd5b833561314381613a8a565b9250602084013561315381613a8a565b929592945050506040919091013590565b60008060008060808587031215613179578081fd5b843561318481613a8a565b9350602085013561319481613a8a565b925060408501359150606085013567ffffffffffffffff8111156131b6578182fd5b8501601f810187136131c6578182fd5b6131d587823560208401612ffa565b91505092959194509250565b600080604083850312156131f3578182fd5b82356131fe81613a8a565b915060208301356130cf81613aaf565b60008060408385031215613220578182fd5b823561322b81613a8a565b946020939093013593505050565b6000602080838503121561324b578182fd5b825167ffffffffffffffff80821115613262578384fd5b818501915085601f830112613275578384fd5b81518181111561328157fe5b8381029150613291848301613a3a565b8181528481019084860184860187018a10156132ab578788fd5b8795505b838610156132cd5780518352600195909501949186019186016132af565b5098975050505050505050565b6000602082840312156132eb578081fd5b8151610c5981613aaf565b600060208284031215613307578081fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610c59578182fd5b600060208284031215613347578081fd5b813567ffffffffffffffff81111561335d578182fd5b8201601f8101841361336d578182fd5b61276484823560208401612ffa565b60006020828403121561338d578081fd5b5035919050565b6000602082840312156133a5578081fd5b5051919050565b60008084546001808216600081146133cb57600181146134005761342f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083168652607f60028404168601935061342f565b600283048886526020808720875b838110156134275781548a82015290850190820161340e565b505050860193505b5050508351613442818360208801613a5e565b01949350505050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b818110156134e057835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016134ae565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156134e057835183529284019291840191600101613508565b901515815260200190565b600060208252825180602084015261354e816040850160208701613a5e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60208082526017908201527f4552433732313a207472616e73666572206661696c6564000000000000000000604082015260600190565b60208082526019908201527f4552433732313a20746f6b656e206e6f6e6578697374616e7400000000000000604082015260600190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460408201527f7265737300000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526019908201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604082015260600190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606082015260800190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760408201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560408201527f726f206164647265737300000000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460408201527f656e7420746f6b656e0000000000000000000000000000000000000000000000606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201527f697374656e7420746f6b656e0000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201527f73206e6f74206f776e0000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60408201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000606082015260800190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560408201527f7200000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60408201527f776e6572206e6f7220617070726f766564000000000000000000000000000000606082015260800190565b6020808252818101527f4552433732313a20746f6b656e207175657279206f7574206f6620626f6e6473604082015260600190565b90815260200190565b60405181810167ffffffffffffffff81118282101715613a5657fe5b604052919050565b60005b83811015613a79578181015183820152602001613a61565b838111156107e55750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114613aac57600080fd5b50565b8015158114613aac57600080fdfea264697066735822122020ea2ca932672bbc490c4a4b6d10d045fe19c8eafc65e4ab82a60bc1c19e5c5464736f6c6343000706003360806040523480156200001157600080fd5b5060405162000bdd38038062000bdd8339810160408190526200003491620001c6565b8151620000499060009060208501906200007f565b5080516200005f9060019060208401906200007f565b5050600280546001600160a01b031916331790555060006003556200022d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282620000b7576000855562000102565b82601f10620000d257805160ff191683800117855562000102565b8280016001018555821562000102579182015b8281111562000102578251825591602001919060010190620000e5565b506200011092915062000114565b5090565b5b8082111562000110576000815560010162000115565b600082601f8301126200013c578081fd5b81516001600160401b03808211156200015157fe5b6040516020601f8401601f19168201810183811183821017156200017157fe5b604052838252858401810187101562000188578485fd5b8492505b83831015620001ab57858301810151828401820152918201916200018c565b83831115620001bc57848185840101525b5095945050505050565b60008060408385031215620001d9578182fd5b82516001600160401b0380821115620001f0578384fd5b620001fe868387016200012b565b9350602085015191508082111562000214578283fd5b5062000223858286016200012b565b9150509250929050565b6109a0806200023d6000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80635a3f26721161007657806370a082311161005b57806370a082311461014357806395d89b4114610156578063c87b56dd1461015e576100a3565b80635a3f2672146101105780636352211e14610130576100a3565b806306fdde03146100a857806307546172146100c657806318160ddd146100db57806340c10f19146100f0575b600080fd5b6100b0610171565b6040516100bd919061084e565b60405180910390f35b6100ce61021d565b6040516100bd91906107de565b6100e3610239565b6040516100bd9190610931565b6101036100fe3660046106e8565b61023f565b6040516100bd9190610843565b61012361011e3660046106ce565b6103ce565b6040516100bd91906107ff565b6100ce61013e3660046107c6565b610448565b6100e36101513660046106ce565b610470565b6100b06104e8565b6100b061016c3660046107c6565b610560565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156102155780601f106101ea57610100808354040283529160200191610215565b820191906000526020600020905b8154815290600101906020018083116101f857829003601f168201915b505050505081565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60035481565b60028054604080518082019091529182527f333100000000000000000000000000000000000000000000000000000000000060208301526000919073ffffffffffffffffffffffffffffffffffffffff1633146102d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102c9919061084e565b60405180910390fd5b5073ffffffffffffffffffffffffffffffffffffffff8316610320576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102c9906108fc565b60035461032e90600161062f565b60035573ffffffffffffffffffffffffffffffffffffffff83166000818152600560209081526040808320805460018101825590845282842001869055858352600490915280822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055518492917f8798af990fbd0ed6b70ef23e11b1a2cd89199d7a4ff28866031fcaadadafcd1391a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602090815260409182902080548351818402810184019094528084526060939283018282801561043b57602002820191906000526020600020905b815481526020019060010190808311610427575b505050505090505b919050565b60009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b600073ffffffffffffffffffffffffffffffffffffffff82166104bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102c99061089f565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526005602052604090205490565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156102155780601f106101ea57610100808354040283529160200191610215565b6002546040517fc87b56dd00000000000000000000000000000000000000000000000000000000815260609173ffffffffffffffffffffffffffffffffffffffff169063c87b56dd906105b7908590600401610931565b60006040518083038186803b1580156105cf57600080fd5b505afa1580156105e3573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106299190810190610711565b92915050565b6000828201838110156106a357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461044357600080fd5b6000602082840312156106df578081fd5b6106a3826106aa565b600080604083850312156106fa578081fd5b610703836106aa565b946020939093013593505050565b600060208284031215610722578081fd5b815167ffffffffffffffff80821115610739578283fd5b818401915084601f83011261074c578283fd5b81518181111561075857fe5b60405160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116820101818110848211171561079457fe5b6040528181528382016020018710156107ab578485fd5b6107bc82602083016020870161093a565b9695505050505050565b6000602082840312156107d7578081fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6020808252825182820181905260009190848201906040850190845b818110156108375783518352928401929184019160010161081b565b50909695505050505050565b901515815260200190565b600060208252825180602084015261086d81604085016020870161093a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560408201527f726f206164647265737300000000000000000000000000000000000000000000606082015260800190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b90815260200190565b60005b8381101561095557818101518382015260200161093d565b83811115610964576000848401525b5050505056fea2646970667358221220e43b2275aeaad452576dc0153c3d5aa9b466665159e300f48e3d34c89587652964736f6c63430007060033000000000000000000000000bbfa3b05b2dae65fb4c05ec7f1598793a4bc06230000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b61626f75743a626c616e6b000000000000000000000000000000000000000000

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

000000000000000000000000bbfa3b05b2dae65fb4c05ec7f1598793a4bc06230000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b61626f75743a626c616e6b000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _controller (address): 0xbBFA3b05b2dAe65Fb4C05Ec7F1598793a4Bc0623
Arg [1] : _baseURI (string): about:blank

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000bbfa3b05b2dae65fb4c05ec7f1598793a4bc0623
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [3] : 61626f75743a626c616e6b000000000000000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

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.