Compare commits
34 Commits
master
...
fediverse-
Author | SHA1 | Date |
---|---|---|
Moon Man | 2eb54beec9 | |
Moon Man | 7bc38210f6 | |
Moon Man | da0a4a98f3 | |
Moon Man | 31aa432ed7 | |
Moon Man | 3a15bf1145 | |
Moon Man | f3e292bec2 | |
Moon Man | cb9898a4bd | |
Moon Man | 791ca05333 | |
Moon Man | a5f9d9f139 | |
Moon Man | bd2cb5aea9 | |
Moon Man | 363d783f42 | |
Moon Man | a4fcf451f5 | |
Moon Man | c2b3b04df7 | |
Moon Man | 4b4922e40b | |
Moon Man | 0677ee477d | |
Moon Man | ad0266bc69 | |
Moon Man | be76f716b1 | |
Moon Man | 4d66247dd3 | |
Moon Man | abb21e0873 | |
Moon Man | 9625c4bdad | |
Moon Man | 01c8e2aefc | |
Moon Man | 691c0c4279 | |
Moon Man | 9a206ffbd3 | |
Moon Man | c29b0a0336 | |
Moon Man | c4d1ab0b7f | |
Moon Man | e430270130 | |
Moon Man | 31f0c6f84e | |
Moon Man | 02a3164658 | |
Moon Man | e8936b07ab | |
Moon Man | 6ede82efa8 | |
Moon Man | dcc29d5d4d | |
Moon Man | 0f93eae7b0 | |
Moon Man | 1c58533f89 | |
Moon Man | ecaa83918f |
|
@ -2,95 +2,167 @@
|
|||
pragma solidity ^0.8.17;
|
||||
|
||||
import "./ERC1155.sol";
|
||||
import "./ICurio.sol";
|
||||
import "./SafeMath.sol";
|
||||
import "./IMastersFedi.sol";
|
||||
import "./Address.sol";
|
||||
import "./IERC1155Metadata.sol";
|
||||
import "./ERC1155Metadata.sol";
|
||||
import "./IERC223ReceivingContract.sol";
|
||||
import "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import "@openzeppelin/contracts/utils/Base64.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/security/Pausable.sol";
|
||||
import "@openzeppelin/contracts/token/common/ERC2981.sol";
|
||||
|
||||
contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI {
|
||||
using SafeMath for uint256;
|
||||
contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI, ERC1155Metadata, ERC2981, IERC223ReceivingContract, Ownable, Pausable {
|
||||
using Address for address;
|
||||
|
||||
// nft id => curio contract address
|
||||
mapping (uint256 => address) public contracts;
|
||||
// nft id => nft metadata IPFS URI
|
||||
mapping (uint256 => string) public metadatas;
|
||||
mapping (uint256 => string) public urls;
|
||||
|
||||
string public name;
|
||||
string public symbol;
|
||||
|
||||
uint96 internal defaultRoyalty;
|
||||
|
||||
struct InitPair {
|
||||
address token;
|
||||
string url;
|
||||
}
|
||||
|
||||
/**
|
||||
@notice Initialize an nft id's data.
|
||||
@notice Initialize an nft id's data
|
||||
*/
|
||||
function create(uint256 _id, address _contract, string memory _uri) internal {
|
||||
function create(uint256 _id, address _contract, string memory _url) internal {
|
||||
|
||||
require(contracts[_id] == address(0), "id already exists");
|
||||
contracts[_id] = _contract;
|
||||
|
||||
urls[_id] = _url;
|
||||
|
||||
// mint 0 just to let explorers know it exists
|
||||
emit TransferSingle(msg.sender, address(0), msg.sender, _id, 0);
|
||||
|
||||
metadatas[_id] = _uri;
|
||||
emit URI(_uri, _id);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
create(1, 0x6Aa2044C7A0f9e2758EdAE97247B03a0D7e73d6c, "ipfs://QmWHUnrdfA4w89TeepZqrvygbaF9wV48k97Wf27skL5cry");
|
||||
create(2, 0xE9A6A26598B05dB855483fF5eCc5f1d0C81140c8, "ipfs://QmVJn6B289Xt3cq9evzubdyk4f1usPAu277SmUusmdYYWU");
|
||||
create(3, 0x3f8131B6E62472CEea9cb8Aa67d87425248a3702, "ipfs://QmWBb6T4nviPWdAyqGJTki7VA6fpTmcYP37U9jpYAfhzPP");
|
||||
create(4, 0x4F1694be039e447B729ab11653304232Ae143C69, "ipfs://Qmbcw8ix8xdK1reFpDEjKtk9EWuRwrbMKqvEvWkttNzXkH");
|
||||
create(5, 0x5a3D4A8575a688b53E8b270b5C1f26fd63065219, "ipfs://QmXmj9YdsvBVddzC352Xsh7bmyJtfZvbVJeetK7PXW21p8");
|
||||
create(6, 0x1Ca6AC0Ce771094F0F8a383D46BF3acC9a5BF27f, "ipfs://Qmdf16YMPM7zG5QkSYB4HjbxQPaStYazsL6d1npdJG8J7h");
|
||||
create(7, 0x2647bd8777e0C66819D74aB3479372eA690912c3, "ipfs://QmUGmWwrNR7JKBCSu3CkGnTYSFat7y2AiUzACcbAoZcj2d");
|
||||
create(8, 0x2FCE2713a561bB019BC5A110BE0A19d10581ee9e, "ipfs://QmXQfBgJRsUQbf8UkViATdpsySXzREsifegWzLvw5QsQPj");
|
||||
create(9, 0xbf4Cc966F1e726087c5C55aac374E687000d4d45, "ipfs://Qmctv89ppbYTuwCWVFA9waVCeE8g6YM3Ah54bZW1WGmEHh");
|
||||
create(10, 0x72b34d637C0d14acE58359Ef1bF472E4b4c57125, "ipfs://QmaSBVrCcBsYHjVuvTsj6ev4Pua7NYX7sDNzdAYwCdAAne");
|
||||
create(11, 0xb36c87F1f1539c5FC6f6e7b1C632e1840C9B66b4, "ipfs://QmZjSs71uBYYdLx5Ju443KiSYjxQcJQLL5ZnhuzWX6nC19");
|
||||
create(12, 0xD15af10A258432e7227367499E785C3532b50271, "ipfs://QmQqMKDMKiRhgbFBrmAJPknzYHEKuH7VrqPZ7NS5vFoy78");
|
||||
create(13, 0x2d922712f5e99428c65b44f09Ea389373d185bB3, "ipfs://QmeShnRPe6uiRcBy81nQXDZ9TWUpFNQfiAThf9ruAQGcRa");
|
||||
create(14, 0x0565ac44e5119a3224b897De761a46A92aA28ae8, "ipfs://Qmdi8vQuQQWksiM5HCCVXfzSzcaemzQwYkUe4Tb94DP6vK");
|
||||
create(15, 0xdb7F262237Ad8acca8922aA2c693a34D0d13e8fe, "ipfs://QmS3UF256kWHbX8Wi7CYExyCxzLNX1nsaMwpaGBN73rr31");
|
||||
create(16, 0x1b63532CcB1FeE0595c7fe2Cb35cFD70ddF862Cd, "ipfs://Qmbj1YCmQidTzxgjLmu1b99PPdXZLSgk72YZQSt9LEEe1R");
|
||||
create(17, 0xF59536290906F204C3c7918D40C1Cc5f99643d0B, "ipfs://QmbDsZABRUPMcuoFWePRH7YiGyR64udWHc4u1mQPJYmB2c");
|
||||
create(18, 0xA507D9d28bbca54cBCfFad4BB770C2EA0519F4F0, "ipfs://QmXafwRpoJPiiQ9TZihhbSsFmgKqKMqrHSRLkp1wyQ3jUU");
|
||||
create(19, 0xf26BC97Aa8AFE176e275Cf3b08c363f09De371fA, "ipfs://QmTWJR1XJ2svexE2NT3A6cCtks8rgh6TKYaLYXwfHapNDN");
|
||||
create(20, 0xD0ec99E99cE22f2487283A087614AEe37F6B1283, "ipfs://Qmd3HzUX52MmZcj1Se3ocgYWEJWSvzSceEqQFV1YL7LRWL");
|
||||
create(21, 0xB7A5a84Ff90e8Ef91250fB56c50a7bB92a6306EE, "ipfs://QmX6stsihT3SNUakiFQLWU1cjvH7rC3pqtCnToxNn2T8JS");
|
||||
create(22, 0x148fF761D16632da89F3D30eF3dFE34bc50CA765, "ipfs://Qmc1sj8LRdfbPinoqKMmAe6UvJUG33VMmSU3XzNK2GnjJB");
|
||||
create(23, 0xCDE7185B5C3Ed9eA68605a960F6653AA1a5b5C6C, "ipfs://Qmdwh3S4imtE5RxZ4ddAzy3DMqNrD11JL6SATTyREuvrtN");
|
||||
create(24, 0xE67dad99c44547B54367E3e60fc251fC45a145C6, "ipfs://QmbfTxH6XvbgGcyWWaygmPko6NQ6tKuT6dJj5WjnQGp5g8");
|
||||
create(25, 0xC7f60C2b1DBDfd511685501EDEb05C4194D67018, "ipfs://QmXHyK19F4sMAUi6XYz1BJJYzxsdp8koVnL4BwsFA93Q47");
|
||||
create(26, 0x1cB5BF4Be53eb141B56f7E4Bb36345a353B5488c, "ipfs://QmYK88qy84rcL46CZGPqpKRm4fE2PQYJ931pV69ZNi4J1D");
|
||||
create(27, 0xFb9F3fa2502d01d43167A0A6E80bE03171DF407E, "ipfs://QmcUTEkPpmRPHCHiXskd9daQcEZwGzkHgybZmCWmFYha1T");
|
||||
create(28, 0x59D190e8A2583C67E62eEc8dA5EA7f050d8BF27e, "ipfs://QmTmi8j5BBE5FWhEDAg1bTqpmkkEcaPgTUeYFJ4z3PxXqN");
|
||||
create(29, 0xD3540bCD9c2819771F9D765Edc189cBD915FEAbd, "ipfs://QmVTGJtgnUgnMPttJV2VkfonCUYLRnJqX66gJLiig5QVgC");
|
||||
create(30, 0x7F5B230Dc580d1e67DF6eD30dEe82684dD113D1F, "ipfs://QmQBu8jYC3vEGzx59BUW4knBdNRyFd8aTVLLFCEprdjZ5e");
|
||||
constructor(string memory _name, string memory _symbol, InitPair[] memory _tokens, uint96 _defaultRoyalty) {
|
||||
name = _name;
|
||||
symbol = _symbol;
|
||||
|
||||
for(uint256 i = 1; i <= _tokens.length; i++) {
|
||||
create(i, _tokens[i].token, _tokens[i].url);
|
||||
}
|
||||
|
||||
_setDefaultRoyalty(msg.sender, _defaultRoyalty);
|
||||
}
|
||||
|
||||
function setDefaultRoyalty(address receiver, uint96 feeNumerator) external onlyOwner {
|
||||
_setDefaultRoyalty(receiver, feeNumerator);
|
||||
}
|
||||
|
||||
function deleteDefaultRoyalty() external onlyOwner {
|
||||
_deleteDefaultRoyalty();
|
||||
}
|
||||
|
||||
/**
|
||||
@dev override ERC1155 uri function to return IPFS ref.
|
||||
@notice Returns URI of token metadata
|
||||
@param _id NFT ID
|
||||
@return IPFS URI pointing to NFT ID's metadata.
|
||||
@return URI data URI of metadata JSON
|
||||
*/
|
||||
function uri(uint256 _id) public view returns (string memory) {
|
||||
return metadatas[_id];
|
||||
function uri(uint256 _id) external override view returns (string memory) {
|
||||
IMastersFedi curio = IMastersFedi(contracts[_id]);
|
||||
|
||||
return string(abi.encodePacked("data:application/json;base64,", Base64.encode(abi.encodePacked(
|
||||
'{',
|
||||
'"name":"', curio.name(), '",',
|
||||
'"description":"', curio.description(), '",',
|
||||
'"image":"ipfs://', curio.ipfs_hash(), '",',
|
||||
'"external_url":"', urls[_id], '",',
|
||||
'"properties":{',
|
||||
'"symbol":"', curio.symbol(), '",',
|
||||
'"erc20_contract":"', Strings.toHexString(contracts[_id]), '"',
|
||||
'}',
|
||||
'}'
|
||||
))));
|
||||
}
|
||||
|
||||
/**
|
||||
@dev helper function to see if NFT ID exists, makes OpenSea happy.
|
||||
@notice Change the external URL for a token
|
||||
@param _id NFT ID
|
||||
@return if NFT ID exists.
|
||||
@param _url URL pointing to user or site
|
||||
*/
|
||||
function setExternalUrl(uint256 _id, string memory _url) external onlyOwner {
|
||||
require(contracts[_id] != address(0), "id must exist");
|
||||
|
||||
urls[_id] = _url;
|
||||
}
|
||||
|
||||
/**
|
||||
@notice Query if a contract implements an interface
|
||||
@param _interfaceId The interface identifier, as specified in ERC-165
|
||||
@return `true` if the contract implements `_interfaceId`
|
||||
*/
|
||||
function supportsInterface(bytes4 _interfaceId) public view override(ERC1155, ERC1155Metadata, ERC2981) returns (bool) {
|
||||
return ERC1155.supportsInterface(_interfaceId)
|
||||
|| ERC1155Metadata.supportsInterface(_interfaceId)
|
||||
|| ERC2981.supportsInterface(_interfaceId)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
@notice If NFT ID exists
|
||||
@dev Makes OpenSea happy
|
||||
@param _id NFT ID
|
||||
@return exists if NFT ID exists.
|
||||
*/
|
||||
function exists(uint256 _id) external view returns(bool) {
|
||||
return contracts[_id] != address(0);
|
||||
}
|
||||
|
||||
bool public destroyable = true;
|
||||
|
||||
/**
|
||||
@dev for an NFT ID, queries and transfers tokens from the appropriate
|
||||
curio contract to itself, and mints and transfers corresponding new
|
||||
ERC-1155 tokens to caller.
|
||||
@notice Destroy the contract
|
||||
@dev Only if it hasn't been disabled
|
||||
*/
|
||||
function destroy() external onlyOwner whenPaused {
|
||||
require(destroyable, "destroy() has been disabled");
|
||||
selfdestruct(payable(msg.sender));
|
||||
}
|
||||
|
||||
function disableDestroy() external onlyOwner {
|
||||
destroyable = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@dev called by token 1 contract after transfer, this is the only method to wrap 1.
|
||||
*/
|
||||
function wrap(uint256 _id, uint256 _quantity) external {
|
||||
function tokenFallback(address _from, uint256 _value, bytes memory) override external {
|
||||
require(_from == owner(), "Only owner can wrap token 1");
|
||||
require(msg.sender == contracts[1] , "Can only transfer from token 1 owner");
|
||||
IMastersFedi curio = IMastersFedi(contracts[1]);
|
||||
require (curio.balanceOf(address(this)) <= 450, "Sanity transfer exceeded");
|
||||
// no balance check is done because an overflow would fail the sanity check anyway
|
||||
|
||||
balances[1][_from] += _value;
|
||||
|
||||
// mint
|
||||
emit TransferSingle(msg.sender, address(0), _from, 1, _value);
|
||||
|
||||
// safe transfer acceptance check not necessary because locked to a known contract
|
||||
}
|
||||
|
||||
/**
|
||||
@notice Converts old-style NFT to new-style
|
||||
@dev For an NFT ID, queries and transfers tokens from the appropriate
|
||||
curio contract to itself, and mints and transfers corresponding new
|
||||
ERC-1155 tokens to caller
|
||||
@param _id NFT ID
|
||||
@param _quantity how many to wrap
|
||||
*/
|
||||
function wrap(uint256 _id, uint256 _quantity) external whenNotPaused {
|
||||
address tokenContract = contracts[_id];
|
||||
require(tokenContract != address(0), "invalid id");
|
||||
ICurio curio = ICurio(tokenContract);
|
||||
require(_id != 1, "cannot wrap token 1 this way");
|
||||
IMastersFedi curio = IMastersFedi(tokenContract);
|
||||
|
||||
// these are here for convenience because curio contract doesn't throw meaningful exceptions
|
||||
require(curio.balanceOf(msg.sender) >= _quantity, "insufficient curio balance");
|
||||
|
@ -98,72 +170,79 @@ contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI {
|
|||
|
||||
curio.transferFrom(msg.sender, address(this), _quantity);
|
||||
|
||||
balances[_id][msg.sender] = balances[_id][msg.sender].add(_quantity);
|
||||
balances[_id][msg.sender] += _quantity;
|
||||
|
||||
// mint
|
||||
emit TransferSingle(msg.sender, address(0), msg.sender, _id, _quantity);
|
||||
|
||||
address _to = msg.sender;
|
||||
if (_to.isContract()) {
|
||||
if (msg.sender.isContract()) {
|
||||
_doSafeTransferAcceptanceCheck(msg.sender, msg.sender, msg.sender, _id, _quantity, '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@dev batch version of wrap.
|
||||
@notice Batch version of wrap function
|
||||
@param _ids array of NFT IDs
|
||||
@param _quantities how many to wrap of each
|
||||
*/
|
||||
function wrapBatch(uint256[] calldata _ids, uint256[] calldata _quantities) external {
|
||||
function wrapBatch(uint256[] calldata _ids, uint256[] calldata _quantities) external whenNotPaused {
|
||||
require(_ids.length == _quantities.length, "ids and quantities must match");
|
||||
|
||||
address _to = msg.sender;
|
||||
bool callerIsContract = _to.isContract();
|
||||
|
||||
for (uint256 i=0; i < _ids.length; ++i) {
|
||||
uint256 _id = _ids[i];
|
||||
uint256 _quantity = _quantities[i];
|
||||
|
||||
address tokenContract = contracts[_id];
|
||||
require(tokenContract != address(0), "invalid id");
|
||||
ICurio curio = ICurio(tokenContract);
|
||||
require(_id != 1, "cannot wrap token 1 this way");
|
||||
IMastersFedi curio = IMastersFedi(tokenContract);
|
||||
|
||||
require(curio.balanceOf(msg.sender) >= _quantity, "insufficient curio balance");
|
||||
require(curio.allowance(msg.sender, address(this)) >= _quantity, "insufficient curio allowance");
|
||||
|
||||
curio.transferFrom(msg.sender, address(this), _quantity);
|
||||
|
||||
balances[_id][msg.sender] = balances[_id][msg.sender].add(_quantity);
|
||||
balances[_id][msg.sender] += _quantity;
|
||||
|
||||
if (callerIsContract) {
|
||||
if (msg.sender.isContract()) {
|
||||
_doSafeTransferAcceptanceCheck(msg.sender, msg.sender, msg.sender, _id, _quantity, '');
|
||||
}
|
||||
}
|
||||
|
||||
// mint
|
||||
emit TransferBatch(msg.sender, address(0), _to, _ids, _quantities);
|
||||
emit TransferBatch(msg.sender, address(0), msg.sender, _ids, _quantities);
|
||||
}
|
||||
|
||||
/**
|
||||
@dev for an NFT ID, burns ERC-1155 quantity and transfers curio ERC-20
|
||||
tokens to caller.
|
||||
@notice Unwrap new-style NFTs back to old-style
|
||||
@dev For an NFT ID, burns ERC-1155 quantity and transfers curio ERC-20
|
||||
tokens to caller
|
||||
@param _id NFT ID
|
||||
@param _quantity how many to unwrap
|
||||
*/
|
||||
function unwrap(uint256 _id, uint256 _quantity) external {
|
||||
function unwrap(uint256 _id, uint256 _quantity) external whenNotPaused {
|
||||
address tokenContract = contracts[_id];
|
||||
require(tokenContract != address(0), "invalid id");
|
||||
ICurio curio = ICurio(tokenContract);
|
||||
require(_id != 1, "token 1 cannot be unwrapped");
|
||||
IMastersFedi curio = IMastersFedi(tokenContract);
|
||||
|
||||
require(balances[_id][msg.sender] >= _quantity, "insufficient balance");
|
||||
balances[_id][msg.sender] = balances[_id][msg.sender].sub(_quantity);
|
||||
balances[_id][msg.sender] -= _quantity;
|
||||
|
||||
curio.transfer(msg.sender, _quantity);
|
||||
// do it this way to make sure there's a transfer event
|
||||
curio.approve(address(this), _quantity);
|
||||
curio.transferFrom(address(this), msg.sender, _quantity);
|
||||
|
||||
// burn
|
||||
emit TransferSingle(msg.sender, msg.sender, address(0), _id, _quantity);
|
||||
}
|
||||
|
||||
/**
|
||||
@dev batch version of unwrap.
|
||||
@notice Batch version of unwrap
|
||||
@param _ids array of NFT IDs
|
||||
@param _quantities how many to unwrap of each
|
||||
*/
|
||||
function unwrapBatch(uint256[] calldata _ids, uint256[] calldata _quantities) external {
|
||||
function unwrapBatch(uint256[] calldata _ids, uint256[] calldata _quantities) external whenNotPaused {
|
||||
require(_ids.length == _quantities.length, "ids and quantities must match");
|
||||
|
||||
for (uint256 i=0; i < _ids.length; ++i) {
|
||||
|
@ -172,12 +251,15 @@ contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI {
|
|||
|
||||
address tokenContract = contracts[_id];
|
||||
require(tokenContract != address(0), "invalid id");
|
||||
ICurio curio = ICurio(tokenContract);
|
||||
require(_id != 1, "token 1 cannot be unwrapped");
|
||||
IMastersFedi curio = IMastersFedi(tokenContract);
|
||||
|
||||
require(balances[_id][msg.sender] >= _quantity, "insufficient balance");
|
||||
balances[_id][msg.sender] = balances[_id][msg.sender].sub(_quantity);
|
||||
balances[_id][msg.sender] -= _quantity;
|
||||
|
||||
curio.transfer(msg.sender, _quantity);
|
||||
// do it this way to make sure there's a transfer event
|
||||
curio.approve(address(this), _quantity);
|
||||
curio.transferFrom(address(this), msg.sender, _quantity);
|
||||
}
|
||||
|
||||
// burn
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
import "./SafeMath.sol";
|
||||
import "./Address.sol";
|
||||
import "./Common.sol";
|
||||
import "./IERC1155TokenReceiver.sol";
|
||||
import "./IERC1155.sol";
|
||||
import "@openzeppelin/contracts/interfaces/IERC165.sol";
|
||||
|
||||
// A sample implementation of core ERC1155 function.
|
||||
contract ERC1155 is IERC1155, ERC165, CommonConstants
|
||||
contract ERC1155 is IERC1155, IERC165, CommonConstants
|
||||
{
|
||||
using SafeMath for uint256;
|
||||
using Address for address;
|
||||
|
||||
// id => (owner => balance)
|
||||
|
@ -38,7 +36,8 @@ contract ERC1155 is IERC1155, ERC165, CommonConstants
|
|||
|
||||
function supportsInterface(bytes4 _interfaceId)
|
||||
public
|
||||
pure
|
||||
view
|
||||
virtual
|
||||
returns (bool) {
|
||||
if (_interfaceId == INTERFACE_SIGNATURE_ERC165 ||
|
||||
_interfaceId == INTERFACE_SIGNATURE_ERC1155) {
|
||||
|
@ -69,10 +68,8 @@ contract ERC1155 is IERC1155, ERC165, CommonConstants
|
|||
require(_to != address(0x0), "_to must be non-zero.");
|
||||
require(_from == msg.sender || operatorApproval[_from][msg.sender] == true, "Need operator approval for 3rd party transfers.");
|
||||
|
||||
// SafeMath will throw with insuficient funds _from
|
||||
// or if _id is not valid (balance will be 0)
|
||||
balances[_id][_from] = balances[_id][_from].sub(_value);
|
||||
balances[_id][_to] = _value.add(balances[_id][_to]);
|
||||
balances[_id][_from] -= _value;
|
||||
balances[_id][_to] += _value;
|
||||
|
||||
// MUST emit event
|
||||
emit TransferSingle(msg.sender, _from, _to, _id, _value);
|
||||
|
@ -111,10 +108,8 @@ contract ERC1155 is IERC1155, ERC165, CommonConstants
|
|||
uint256 id = _ids[i];
|
||||
uint256 value = _values[i];
|
||||
|
||||
// SafeMath will throw with insuficient funds _from
|
||||
// or if _id is not valid (balance will be 0)
|
||||
balances[id][_from] = balances[id][_from].sub(value);
|
||||
balances[id][_to] = value.add(balances[id][_to]);
|
||||
balances[id][_from] -= value;
|
||||
balances[id][_to] += value;
|
||||
}
|
||||
|
||||
// Note: instead of the below batch versions of event and acceptance check you MAY have emitted a TransferSingle
|
||||
|
@ -136,7 +131,7 @@ contract ERC1155 is IERC1155, ERC165, CommonConstants
|
|||
@notice Get the balance of an account's Tokens.
|
||||
@param _owner The address of the token holder
|
||||
@param _id ID of the Token
|
||||
@return The _owner's balance of the Token type requested
|
||||
@return balance The _owner's balance of the Token type requested
|
||||
*/
|
||||
function balanceOf(address _owner, uint256 _id) external view returns (uint256) {
|
||||
// The balance of any account can be calculated from the Transfer events history.
|
||||
|
@ -150,7 +145,7 @@ contract ERC1155 is IERC1155, ERC165, CommonConstants
|
|||
@notice Get the balance of multiple account/token pairs
|
||||
@param _owners The addresses of the token holders
|
||||
@param _ids ID of the Tokens
|
||||
@return The _owner's balance of the Token types requested (i.e. balance for each (owner, id) pair)
|
||||
@return balance The _owner's balance of the Token types requested (i.e. balance for each (owner, id) pair)
|
||||
*/
|
||||
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory) {
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
import "./IERC1155Metadata.sol";
|
||||
|
||||
contract ERC1155Metadata {
|
||||
|
||||
/**
|
||||
@notice Query if a contract implements an interface
|
||||
@param _interfaceId The interface identifier, as specified in ERC-165
|
||||
@return `true` if the contract implements `_interfaceID`
|
||||
*/
|
||||
function supportsInterface(bytes4 _interfaceId) public virtual view returns (bool) {
|
||||
if (_interfaceId == type(ERC1155Metadata_URI).interfaceId) {
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
import "./ERC165.sol";
|
||||
|
||||
/**
|
||||
@title ERC-1155 Multi Token Standard
|
||||
@dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
interface IERC223ReceivingContract {
|
||||
function tokenFallback(address _from, uint256 _value, bytes memory _data) external;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
import "@openzeppelin/contracts/interfaces/IERC165.sol";
|
||||
|
||||
interface IERC2981 is IERC165 {
|
||||
/// ERC165 bytes to add to interface array - set in parent contract
|
||||
/// implementing this standard
|
||||
///
|
||||
/// bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a
|
||||
/// bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
|
||||
/// _registerInterface(_INTERFACE_ID_ERC2981);
|
||||
|
||||
/// @notice Called with the sale price to determine how much royalty
|
||||
// is owed and to whom.
|
||||
/// @param _tokenId - the NFT asset queried for royalty information
|
||||
/// @param _salePrice - the sale price of the NFT asset specified by _tokenId
|
||||
/// @return receiver - address of who should be sent the royalty payment
|
||||
/// @return royaltyAmount - the royalty payment amount for _salePrice
|
||||
function royaltyInfo(
|
||||
uint256 _tokenId,
|
||||
uint256 _salePrice
|
||||
) external view returns (
|
||||
address receiver,
|
||||
uint256 royaltyAmount
|
||||
);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
// Masters of the Fediverse is not quite ERC-20 compliant
|
||||
interface IMastersFedi {
|
||||
function balanceOf(address account) external view returns (uint256);
|
||||
function allowance(address owner, address spender) external view returns (uint256);
|
||||
function approve(address _spender, uint256 _value) external returns (bool success);
|
||||
function transferFrom(address _from, address _to, uint256 _value) external;
|
||||
function transfer(address _to, uint256 _value) external;
|
||||
function ipfs_hash() external view returns (string memory);
|
||||
function name() external view returns (string memory);
|
||||
function symbol() external view returns (string memory);
|
||||
function description() external view returns (string memory);
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
|
||||
/**
|
||||
* @title SafeMath
|
||||
* @dev Math operations with safety checks that throw on error
|
||||
*/
|
||||
library SafeMath {
|
||||
|
||||
/**
|
||||
* @dev Multiplies two numbers, throws on overflow.
|
||||
*/
|
||||
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
|
||||
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the
|
||||
// benefit is lost if 'b' is also tested.
|
||||
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = a * b;
|
||||
assert(c / a == b);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Integer division of two numbers, truncating the quotient.
|
||||
*/
|
||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// assert(b > 0); // Solidity automatically throws when dividing by 0
|
||||
// uint256 c = a / b;
|
||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
||||
return a / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
assert(b <= a);
|
||||
return a - b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds two numbers, throws on overflow.
|
||||
*/
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
|
||||
c = a + b;
|
||||
assert(c >= a);
|
||||
return c;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,23 @@
|
|||
const CurioWrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
|
||||
const tokens = [
|
||||
{ token: "0x2f873FCc3F4B84E9A62AFf28E9a897ce1BC8814B", url: "https://shitposter.club" }, // 1 is the ERC-223
|
||||
{ token: "0x13a9914Ad2e0be57eB2Abb3E159021Eab6D7a80E", url: "https://tuusin.misono-ya.info/users/hakui" },
|
||||
{ token: "0xdeCAa5B6901dc465FBf90f9C0c70c96132aF51Db", url: "https://shitposter.club/users/augustus" },
|
||||
{ token: "0xc1de7E95663FB3A0e8F8C6E6a64297d7AbcBF7f7", url: "https://xj-ix.luxe/bin/fedi" },
|
||||
{ token: "0xB70F9A809693B8c6a4c331342B96F15252521dC7", url: "https://varishangout.net/users/nepfag" },
|
||||
{ token: "0x3f2592136d90dE35615A409B4fe710B3764366F4", url: "https://shitposter.club/dokidoki@pl.smuglo.li" },
|
||||
{ token: "0x5e7318f75b177a0F27A31CB20bB26bd0C049620c", url: "https://twitter.com/sonyasupposedly" },
|
||||
{ token: "0x5539907D45a608828756765429f2B4e6311c295c", url: "https://shpposter.club/users/shpuld" },
|
||||
{ token: "0x0a0e64067B1F7aDfbF876Dde4322633Ff7Df9702", url: "https://bbs.kawa-kun.com/users/tk" }
|
||||
];
|
||||
|
||||
module.exports = function(deployer) {
|
||||
deployer.deploy(CurioWrapper);
|
||||
deployer.deploy(
|
||||
CurioWrapper,
|
||||
"Masters of the Fediverse",
|
||||
"MASTERS",
|
||||
tokens,
|
||||
200 // default royalty 2%
|
||||
);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
"name": "curio-wrapper",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@openzeppelin/contracts": "^4.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@truffle/hdwallet-provider": "^1.7.0",
|
||||
"ganache": "^7.7.3",
|
||||
|
@ -1278,6 +1281,11 @@
|
|||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@openzeppelin/contracts": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.1.tgz",
|
||||
"integrity": "sha512-xQ6eUZl+RDyb/FiZe1h+U7qr/f4p/SrTSQcTPH2bjur3C5DbuW/zFgCU/b1P/xcIaEqJep+9ju4xDRi3rmChdQ=="
|
||||
},
|
||||
"node_modules/@protobufjs/aspromise": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
|
||||
|
@ -12336,6 +12344,11 @@
|
|||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"@openzeppelin/contracts": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.1.tgz",
|
||||
"integrity": "sha512-xQ6eUZl+RDyb/FiZe1h+U7qr/f4p/SrTSQcTPH2bjur3C5DbuW/zFgCU/b1P/xcIaEqJep+9ju4xDRi3rmChdQ=="
|
||||
},
|
||||
"@protobufjs/aspromise": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
|
||||
|
|
|
@ -19,5 +19,8 @@
|
|||
"@truffle/hdwallet-provider": "^1.7.0",
|
||||
"ganache": "^7.7.3",
|
||||
"truffle": "^5.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@openzeppelin/contracts": "^4.8.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
const IMastersFedi = artifacts.require("IMastersFedi");
|
||||
|
||||
const quantity = parseInt(process.argv[6]);
|
||||
|
||||
module.exports = async (callback) => {
|
||||
if (quantity > 0) {
|
||||
const wrapper = await Wrapper.deployed();
|
||||
|
||||
let approveSuccess = false;
|
||||
console.log("Approving all contracts for transfer");
|
||||
try {
|
||||
for (let id = 2; id <= 9; ++id) {
|
||||
const tokenContractAddress = await wrapper.contracts(id);
|
||||
const tokenContract = await IMastersFedi.at(tokenContractAddress);
|
||||
|
||||
console.log(`Approving ID ${id}...`);
|
||||
await tokenContract.approve(wrapper.address, quantity);
|
||||
}
|
||||
approveSuccess = true;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error("Invalid quantity");
|
||||
}
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
const IMastersFedi = artifacts.require("IMastersFedi");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const nftId1 = parseInt(process.argv[6]);
|
||||
|
||||
const wrapper = await Wrapper.deployed();
|
||||
const tokenContractAddress1 = await wrapper.contracts(nftId1);
|
||||
const tokenContract1 = await IMastersFedi.at(tokenContractAddress1);
|
||||
const tokenName1 = await tokenContract1.name();
|
||||
console.log(`Token name: "${tokenName1}"`);
|
||||
|
||||
const [account,] = await web3.eth.getAccounts();
|
||||
|
||||
const whom = process.argv[7] ? process.argv[7] : account;
|
||||
|
||||
const wrappedBalance1 = await wrapper.balanceOf(whom, nftId1);
|
||||
const tokenBalance1 = await tokenContract1.balanceOf(whom);
|
||||
console.log(`Wrapped: ${wrappedBalance1}`);
|
||||
console.log(`Unwrapped: ${tokenBalance1}`);
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
const IMastersFedi = artifacts.require("IMastersFedi");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const nftId1 = parseInt(process.argv[6]);
|
||||
const quantity1 = parseInt(process.argv[7]);
|
||||
const nftId2 = parseInt(process.argv[8]);
|
||||
const quantity2 = parseInt(process.argv[9]);
|
||||
|
||||
const wrapper = await Wrapper.deployed();
|
||||
const tokenContractAddress1 = await wrapper.contracts(nftId1);
|
||||
const tokenContractAddress2 = await wrapper.contracts(nftId2);
|
||||
const tokenContract1 = await IMastersFedi.at(tokenContractAddress1);
|
||||
const tokenContract2 = await IMastersFedi.at(tokenContractAddress2);
|
||||
const tokenName1 = await tokenContract1.name();
|
||||
const tokenName2 = await tokenContract2.name();
|
||||
console.log(`Token names: "${tokenName1}", "${tokenName2}"`);
|
||||
|
||||
const [account,] = await web3.eth.getAccounts();
|
||||
|
||||
try {
|
||||
console.log("Batch unwrapping...");
|
||||
const finalResult = await wrapper.unwrapBatch(
|
||||
[nftId1, nftId2],
|
||||
[quantity1, quantity2],
|
||||
{ from: account }
|
||||
);
|
||||
|
||||
console.log(`Tx: ${finalResult.tx}`);
|
||||
|
||||
const wrappedBalance1 = await wrapper.balanceOf(account, nftId1);
|
||||
const wrappedBalance2 = await wrapper.balanceOf(account, nftId2);
|
||||
|
||||
console.log(`New wrapped balances: ${wrappedBalance1}, ${wrappedBalance2}`);
|
||||
|
||||
const tokenBalance1 = await tokenContract1.balanceOf(account);
|
||||
const tokenBalance2 = await tokenContract2.balanceOf(account);
|
||||
console.log(`New unwrapped balances: ${tokenBalance1}, ${tokenBalance2}`);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
|
||||
console.log("Done.");
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
const IMastersFedi = artifacts.require("IMastersFedi");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const nftId1 = parseInt(process.argv[6]);
|
||||
const quantity1 = parseInt(process.argv[7]);
|
||||
const nftId2 = parseInt(process.argv[8]);
|
||||
const quantity2 = parseInt(process.argv[9]);
|
||||
|
||||
const wrapper = await Wrapper.deployed();
|
||||
const tokenContractAddress1 = await wrapper.contracts(nftId1);
|
||||
const tokenContractAddress2 = await wrapper.contracts(nftId2);
|
||||
const tokenContract1 = await IMastersFedi.at(tokenContractAddress1);
|
||||
const tokenContract2 = await IMastersFedi.at(tokenContractAddress2);
|
||||
const tokenName1 = await tokenContract1.name();
|
||||
const tokenName2 = await tokenContract2.name();
|
||||
console.log(`Token names: "${tokenName1}", "${tokenName2}"`);
|
||||
|
||||
const [account,] = await web3.eth.getAccounts();
|
||||
const tokenBalance1 = await tokenContract1.balanceOf(account);
|
||||
const tokenBalance2 = await tokenContract2.balanceOf(account);
|
||||
console.log(`Unwrapped balances: ${tokenBalance1}, ${tokenBalance2}`);
|
||||
|
||||
|
||||
try {
|
||||
console.log(`Approving token 1...`);
|
||||
const result1 = await tokenContract1.approve(wrapper.address, quantity1, { from: account });
|
||||
console.log(`Approving token 2...`);
|
||||
const result2 = await tokenContract2.approve(wrapper.address, quantity2, { from: account });
|
||||
|
||||
console.log("Batch wrapping...");
|
||||
const finalResult = await wrapper.wrapBatch(
|
||||
[nftId1, nftId2],
|
||||
[quantity1, quantity2],
|
||||
{ from: account }
|
||||
);
|
||||
|
||||
console.log(`Tx: ${finalResult.tx}`);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
|
||||
console.log("Done.");
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const wrapper = await Wrapper.deployed();
|
||||
|
||||
const name = await wrapper.name();
|
||||
const symbol = await wrapper.symbol();
|
||||
|
||||
console.log(`Name: "${name}", symbol: "${symbol}"`);
|
||||
|
||||
const { 0:receiver, 1:hexAmount} = await wrapper.royaltyInfo(1, "1000000000000000000");
|
||||
console.log(`Default royalty recipient: ${receiver}`);
|
||||
|
||||
const ubiqAmount = web3.utils.fromWei(hexAmount, "ether");
|
||||
console.log(`Royalty on a 1 Ubiq fee: ${ubiqAmount}`);
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const nftId = parseInt(process.argv[6]);
|
||||
console.log(`Querying metadata for ID: ${nftId}`);
|
||||
|
||||
const wrapper = await Wrapper.deployed();
|
||||
|
||||
const dataURI = await wrapper.uri(nftId);
|
||||
console.log(`Data URI: ${dataURI}`);
|
||||
|
||||
const data = dataURI.split(',')[1];
|
||||
const raw = Buffer.from(data, "base64").toString("utf8");
|
||||
console.log(JSON.stringify(JSON.parse(raw), null, 4));
|
||||
|
||||
console.log("Done.");
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
|
||||
const MAX = 7.5;
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const receiver = process.argv[6];
|
||||
if (/0x[0-9a-fA-F]{40}/.test(receiver)) {
|
||||
const percentage = parseFloat(process.argv[7]);
|
||||
if (percentage > 0 && percentage <= MAX) {
|
||||
const numerator = Math.ceil(percentage * 100);
|
||||
console.log(`Numerator to be used: ${numerator}`);
|
||||
|
||||
const wrapper = await Wrapper.deployed();
|
||||
|
||||
console.log("Exeuting transaction...");
|
||||
try {
|
||||
await wrapper.setDefaultRoyalty(receiver, numerator);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error(`Royalty must be greater than zero and less than %${percentage}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error("Invalid receiver address");
|
||||
}
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
|
||||
const interfaceId = process.argv[6];
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const wrapper = await Wrapper.deployed();
|
||||
|
||||
const supports = await wrapper.supportsInterface(interfaceId);
|
||||
console.log(`Supports interface: ${supports}`);
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const nftId1 = parseInt(process.argv[6]);
|
||||
const quantity1 = BigInt(process.argv[7]);
|
||||
const to = process.argv[8];
|
||||
|
||||
if (/0x[0-9a-fA-F]{40}/.test(to)) {
|
||||
const wrapper = await Wrapper.deployed();
|
||||
|
||||
const [account,] = await web3.eth.getAccounts();
|
||||
|
||||
const from = process.argv[9] ? process.argv[9] : account;
|
||||
if (from !== account) {
|
||||
console.log(`Overrode from address`);
|
||||
const approved = await wrapper.isApprovedForAll(from, account);
|
||||
console.log(`Approved? ${approved ? "yes" : "no"}`);
|
||||
}
|
||||
|
||||
const currentBalance = BigInt(await wrapper.balanceOf(from, nftId1));
|
||||
console.log(`Current balance: ${currentBalance}`);
|
||||
|
||||
if (currentBalance >= quantity1) {
|
||||
console.log("Executing transfer transaction...");
|
||||
try {
|
||||
const result = await wrapper.safeTransferFrom(from, to, nftId1, quantity1.toString(), []);
|
||||
console.log(`Transaction: ${result.tx}`);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error("Insufficient balance");
|
||||
}
|
||||
}
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
const IMastersFedi = artifacts.require("IMastersFedi");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const [account,] = await web3.eth.getAccounts();
|
||||
const quantity = parseInt(process.argv[6]);
|
||||
const to = process.argv[7];
|
||||
|
||||
const tokenContract = await IMastersFedi.at("0x2f873FCc3F4B84E9A62AFf28E9a897ce1BC8814B");
|
||||
const currentBalance = await tokenContract.balanceOf(account);
|
||||
console.log(`Current balance: ${currentBalance}`);
|
||||
|
||||
console.log("Executing transfer transaction...");
|
||||
try {
|
||||
const result = await tokenContract.transfer(to, quantity);
|
||||
console.log(`Transaction: ${result.tx}`);
|
||||
|
||||
const newBalance = await tokenContract.balanceOf(account);
|
||||
console.log(`New balance: ${newBalance}`);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
const IMastersFedi = artifacts.require("IMastersFedi");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const nftId = parseInt(process.argv[6]);
|
||||
const quantity = parseInt(process.argv[7]);
|
||||
console.log(`Quantity to unwrap: ${quantity}`);
|
||||
|
||||
const wrapper = await Wrapper.deployed();
|
||||
const tokenContractAddress = await wrapper.contracts(nftId);
|
||||
const tokenContract = await IMastersFedi.at(tokenContractAddress);
|
||||
const tokenName = await tokenContract.name();
|
||||
console.log(`Token contract address: ${tokenContractAddress}, name: "${tokenName}"`);
|
||||
|
||||
const [account,] = await web3.eth.getAccounts();
|
||||
let wrappedQuantity = await wrapper.balanceOf(account, nftId);
|
||||
console.log(`Wrapped quantity: ${wrappedQuantity}`);
|
||||
|
||||
let result1;
|
||||
try {
|
||||
console.log("Sending unwrap transaction...");
|
||||
result1 = await wrapper.unwrap(nftId, quantity, { from: account });
|
||||
|
||||
wrappedQuantity = await wrapper.balanceOf(account, nftId);
|
||||
console.log(`New wrapped balance: ${wrappedQuantity}`);
|
||||
|
||||
const unwrappedBalance = await tokenContract.balanceOf(account);
|
||||
console.log(`New unwrapped balance: ${unwrappedBalance}`);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
const IMastersFedi = artifacts.require("IMastersFedi");
|
||||
|
||||
const seq = n => n < 1 ? [] : [...seq(n - 1), n];
|
||||
|
||||
const to = process.argv[6];
|
||||
const quantity = parseInt(process.argv[7]);
|
||||
|
||||
module.exports = async (callback) => {
|
||||
if (/0x[0-9a-fA-F]{40}/.test(to) && quantity > 0) {
|
||||
const wrapper = await Wrapper.deployed();
|
||||
const [account,] = await web3.eth.getAccounts();
|
||||
const ids = seq(9);
|
||||
const quantities = Array(9).fill(quantity);
|
||||
|
||||
let approveSuccess = false;
|
||||
console.log("Approving all contracts for transfer");
|
||||
try {
|
||||
for (let id = 1; id <= 9; ++id) {
|
||||
const tokenContractAddress = await wrapper.contracts(id);
|
||||
const tokenContract = await IMastersFedi.at(tokenContractAddress);
|
||||
|
||||
console.log(`Approving ID ${id}...`);
|
||||
await tokenContract.approve(wrapper.address, quantity);
|
||||
}
|
||||
approveSuccess = true;
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
|
||||
if (approveSuccess) {
|
||||
console.log("Executing wrap transaction...");
|
||||
let wrapResult;
|
||||
try {
|
||||
wrapResult = await wrapper.wrapBatch(
|
||||
ids,
|
||||
quantities
|
||||
);
|
||||
console.log(`Wrap transaction: ${wrapResult.tx}`);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
|
||||
if (wrapResult) {
|
||||
console.log("Executing batch transfer...");
|
||||
const transferResult = await wrapper.safeBatchTransferFrom(account, to, ids, quantities, []);
|
||||
console.log(`Transfer transaction: ${transferResult.tx}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error("Invalid to address or quantity");
|
||||
}
|
||||
|
||||
callback();
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
const Wrapper = artifacts.require("CurioERC1155Wrapper");
|
||||
const IMastersFedi = artifacts.require("IMastersFedi");
|
||||
|
||||
module.exports = async (callback) => {
|
||||
const nftId = parseInt(process.argv[6]);
|
||||
const quantity = parseInt(process.argv[7]);
|
||||
console.log(`Quantity to wrap: ${quantity}`);
|
||||
|
||||
const wrapper = await Wrapper.deployed();
|
||||
const tokenContractAddress = await wrapper.contracts(nftId);
|
||||
const tokenContract = await IMastersFedi.at(tokenContractAddress);
|
||||
const tokenName = await tokenContract.name();
|
||||
console.log(`Token contract address: ${tokenContractAddress}, name: "${tokenName}"`);
|
||||
|
||||
const [account,] = await web3.eth.getAccounts();
|
||||
const tokenQuantity = await tokenContract.balanceOf(account);
|
||||
console.log(`Unwrapped balance: ${tokenQuantity}`);
|
||||
|
||||
if (tokenQuantity >= quantity) {
|
||||
console.log("First approving contract to withdraw token quantity...");
|
||||
let result1;
|
||||
try {
|
||||
result1 = await tokenContract.approve(wrapper.address, quantity, { from: account });
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
|
||||
if (result1) {
|
||||
console.log("Now submitting wrap transaction...");
|
||||
let result;
|
||||
|
||||
try {
|
||||
result = await wrapper.wrap(nftId, quantity, { from: account });
|
||||
console.log(`Transaction: ${result.tx}`);
|
||||
|
||||
const wrappedQuantity = await wrapper.balanceOf(account, nftId);
|
||||
console.log(`New wrapped quantity: ${wrappedQuantity}`);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`FAILED: ${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error("Insufficient balance");
|
||||
}
|
||||
|
||||
console.log("Done.");
|
||||
callback();
|
||||
}
|
|
@ -54,8 +54,8 @@ module.exports = {
|
|||
},
|
||||
ubiq: {
|
||||
provider: () => new HDWalletProvider(mnemonic, "https://rpc.octano.dev"),
|
||||
gas: 5500000,
|
||||
network_id: 88,
|
||||
gas: 6150000,
|
||||
network_id: 8,
|
||||
confirmations: 2,
|
||||
timeoutBlocks: 200,
|
||||
skipDryRun: true
|
||||
|
@ -80,7 +80,10 @@ module.exports = {
|
|||
// settings: { // See the solidity docs for advice about optimization and evmVersion
|
||||
optimizer: {
|
||||
enabled: true,
|
||||
runs: 200
|
||||
runs: 1
|
||||
},
|
||||
debug: {
|
||||
revertStrings: "strip"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue