账户
0x68...bc46
0x68...Bc46

0x68...Bc46

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.5.4+commit.9549d8ff
语言
Solidity
合同源代码
文件 1 的 1:ERC721Converter.sol
pragma solidity ^0.5.0;
// produced by the Solididy File Flattener (c) David Appleton 2018
// contact : dave@akomba.com
// released under Apache 2.0 licence
// input  /Users/rmanzoku/src/github.com/doublejumptokyo/erc721/contracts/erc721converter.sol
// flattened :  Monday, 26-Aug-19 06:45:45 UTC
contract Ownable {
    address private _owner;

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

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

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Returns true if the caller is the current owner.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == _owner;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * > Note: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    /**
     * @dev Give an account access to this role.
     */
    function add(Role storage role, address account) internal {
        require(!has(role, account), "Roles: account already has role");
        role.bearer[account] = true;
    }

    /**
     * @dev Remove an account's access to this role.
     */
    function remove(Role storage role, address account) internal {
        require(has(role, account), "Roles: account does not have role");
        role.bearer[account] = false;
    }

    /**
     * @dev Check if an account has this role.
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

contract IERC721Receiver {
    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     * after a `safeTransfer`. This function MUST return the function selector,
     * otherwise the caller will revert the transaction. The selector to be
     * returned can be obtained as `this.onERC721Received.selector`. This
     * function MAY throw to revert and reject the transfer.
     * Note: the ERC721 contract address is always the message sender.
     * @param operator The address which called `safeTransferFrom` function
     * @param from The address which previously owned the token
     * @param tokenId The NFT identifier which is being transferred
     * @param data Additional data with no specified format
     * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
    public returns (bytes4);
}

interface ERC721 /* is ERC165 */ {
  event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
  event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
  event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
  function balanceOf(address _owner) external view returns (uint256);
  function ownerOf(uint256 _tokenId) external view returns (address);
  function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;
  function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
  function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
  function approve(address _approved, uint256 _tokenId) external payable;
  function setApprovalForAll(address _operator, bool _approved) external;
  function getApproved(uint256 _tokenId) external view returns (address);
  function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}

interface ERC165 {
  function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

contract ERC721Holder is IERC721Receiver {
    function onERC721Received(address, address, uint256, bytes memory) public returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

contract OperatorRole is Ownable {
  using Roles for Roles.Role;

  event OperatorAdded(address indexed account);
  event OperatorRemoved(address indexed account);

  event Paused(address account);
  event Unpaused(address account);

  bool private _paused;

  Roles.Role private operators;

  constructor() public {
    operators.add(msg.sender);
    _paused = false;
  }

  modifier onlyOperator() {
    require(isOperator(msg.sender));
    _;
  }

  modifier whenNotPaused() {
    require(!_paused, "Pausable: paused");
    _;
  }

  modifier whenPaused() {
    require(_paused, "Pausable: not paused");
    _;
  }

  function isOperator(address account) public view returns (bool) {
    return operators.has(account);
  }

  function addOperator(address account) public onlyOwner() {
    operators.add(account);
    emit OperatorAdded(account);
  }

  function removeOperator(address account) public onlyOwner() {
    operators.remove(account);
    emit OperatorRemoved(account);
  }

  function paused() public view returns (bool) {
    return _paused;
  }

  function pause() public onlyOperator() whenNotPaused() {
    _paused = true;
    emit Paused(msg.sender);
  }

  function unpause() public onlyOperator whenPaused() {
    _paused = false;
    emit Unpaused(msg.sender);
  }

}

contract ERC721Converter is ERC721Holder, OperatorRole {
  ERC721 Alice;
  ERC721 Bob;

  address public aliceContract;
  address public bobContract;

  bool public approveOnce = false;

  mapping (uint256 => uint256) private _idMapAliceToBob;
  mapping (uint256 => uint256) private _idMapBobToAlice;

  constructor(address _alice, address _bob) public {
    aliceContract = _alice;
    bobContract = _bob;
    Alice = ERC721(aliceContract);
    Bob = ERC721(bobContract);
  }

  function approve(address _spender) external onlyOwner() {
    require(approveOnce != true);
    Alice.setApprovalForAll(_spender, true);
    Bob.setApprovalForAll(_spender, true);
    approveOnce = true;
  }

  function dismiss(address _spender) external onlyOwner() {
    Alice.setApprovalForAll(_spender, false);
    Bob.setApprovalForAll(_spender, false);
  }

  function updateAlice(address _newAlice) external onlyOperator() {
    aliceContract = _newAlice;
    Alice = ERC721(_newAlice);
  }

  function updateBob(address _newBob) external onlyOperator() {
    bobContract = _newBob;
    Bob = ERC721(_newBob);
  }

  function draftAliceTokens(uint256[] memory _aliceTokenIds, uint256[] memory _bobTokenIds) public onlyOperator() {
    require(_aliceTokenIds.length == _bobTokenIds.length);
    for (uint256 i = 0; i < _aliceTokenIds.length; i++) {
      draftAliceToken(_aliceTokenIds[i], _bobTokenIds[i]);
    }
  }

  function draftBobTokens(uint256[] memory _bobTokenIds, uint256[] memory _aliceTokenIds) public onlyOperator() {
    require(_aliceTokenIds.length == _bobTokenIds.length);
    for (uint256 i = 0; i < _aliceTokenIds.length; i++) {
      draftBobToken(_bobTokenIds[i], _aliceTokenIds[i]);
    }
  }

  function draftAliceToken(uint256 _aliceTokenId, uint256 _bobTokenId) public onlyOperator() {
    require(Alice.ownerOf(_aliceTokenId) == address(this), "_aliceTokenId is not owned");
    require(_idMapAliceToBob[_aliceTokenId] == 0, "_aliceTokenId is already assignd");
    require(_idMapBobToAlice[_bobTokenId] == 0, "_bobTokenId is already assignd");

    _idMapAliceToBob[_aliceTokenId] = _bobTokenId;
    _idMapBobToAlice[_bobTokenId] = _aliceTokenId;
  }

  function draftBobToken(uint256 _bobTokenId, uint256 _aliceTokenId) public onlyOperator() {
    require(Bob.ownerOf(_bobTokenId) == address(this), "_bobTokenId is not owned");
    require(_idMapBobToAlice[_bobTokenId] == 0, "_bobTokenId is already assignd");
    require(_idMapAliceToBob[_aliceTokenId] == 0, "_aliceTokenId is already assignd");

    _idMapBobToAlice[_bobTokenId] = _aliceTokenId;
    _idMapAliceToBob[_aliceTokenId] = _bobTokenId;
  }

  function getBobTokenID(uint256 _aliceTokenId) public view returns(uint256) {
    return _idMapAliceToBob[_aliceTokenId];
  }

  function getAliceTokenID(uint256 _bobTokenId) public view returns(uint256) {
    return _idMapBobToAlice[_bobTokenId];
  }

  function convertFromAliceToBob(uint256 _tokenId) external whenNotPaused() {
    Alice.safeTransferFrom(msg.sender, address(this), _tokenId);
    Bob.safeTransferFrom(address(this), msg.sender, getBobTokenID(_tokenId));
  }

  function convertFromBobToAlice(uint256 _tokenId) external whenNotPaused() {
    Bob.safeTransferFrom(msg.sender, address(this), _tokenId);
    Alice.safeTransferFrom(address(this), msg.sender, getAliceTokenID(_tokenId));
  }
}
设置
{
  "compilationTarget": {
    "ERC721Converter.sol": "ERC721Converter"
  },
  "evmVersion": "byzantium",
  "libraries": {},
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"constant":false,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"name":"","type":"bytes4"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_aliceTokenIds","type":"uint256[]"},{"name":"_bobTokenIds","type":"uint256[]"}],"name":"draftAliceTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_bobTokenId","type":"uint256"}],"name":"getAliceTokenID","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newAlice","type":"address"}],"name":"updateAlice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"convertFromBobToAlice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_bobTokenIds","type":"uint256[]"},{"name":"_aliceTokenIds","type":"uint256[]"}],"name":"draftBobTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isOperator","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newBob","type":"address"}],"name":"updateBob","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_aliceTokenId","type":"uint256"}],"name":"getBobTokenID","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"convertFromAliceToBob","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_bobTokenId","type":"uint256"},{"name":"_aliceTokenId","type":"uint256"}],"name":"draftBobToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"removeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"bobContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"aliceContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"}],"name":"dismiss","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"approveOnce","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_aliceTokenId","type":"uint256"},{"name":"_bobTokenId","type":"uint256"}],"name":"draftAliceToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_alice","type":"address"},{"name":"_bob","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"OperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"OperatorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]