-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
470a3f4
commit aa786cb
Showing
16 changed files
with
1,855 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
//custom abstract implementation of ERC1155 | ||
//used to configure zero trust air drop scenario | ||
import "./extensions/ERC1155AirDroppable.sol"; | ||
|
||
//custom abstract extension of ERC1155 | ||
//used to list tokens for sale and set royalties | ||
import "./extensions/ERC1155ExchangableFees.sol"; | ||
|
||
contract ERC1155AirDrop is | ||
ERC1155AirDroppable, | ||
ERC1155ExchangableFees | ||
{ | ||
//in only the contract owner can add a fee | ||
address owner; | ||
|
||
modifier onlyContractOwner { | ||
require( | ||
msg.sender == owner, | ||
'Restricted method access to only the contract owner' | ||
); | ||
_; | ||
} | ||
|
||
/** | ||
* @dev Constructor function | ||
*/ | ||
constructor (string memory _uri) ERC1155(_uri) { | ||
owner = msg.sender; | ||
} | ||
|
||
/** | ||
* @dev Only the contract owner can airdrop a token | ||
*/ | ||
function drop(uint256 tokenId, bytes32 merkleRoot) public onlyContractOwner { | ||
_drop(tokenId, merkleRoot); | ||
} | ||
|
||
/** | ||
* @dev Only the contract owner can add a fee | ||
*/ | ||
function setFee(uint256 tokenId, address payable recipient, uint256 fee) | ||
public | ||
onlyContractOwner | ||
{ | ||
_setFee(tokenId, recipient, fee); | ||
} | ||
|
||
/** | ||
* @dev Only the contract owner can remove a fee | ||
*/ | ||
function removeFee(uint256 tokenId, address payable recipient) | ||
public | ||
onlyContractOwner | ||
{ | ||
_removeFee(tokenId, recipient); | ||
} | ||
|
||
//minting is disabled | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
//custom abstract extension of ERC1155 | ||
//used to list tokens for sale and set royalties | ||
import "./extensions/ERC1155ExchangableFees.sol"; | ||
|
||
contract ERC1155Exchange is ERC1155ExchangableFees { | ||
//in only the contract owner can add a fee | ||
address owner; | ||
|
||
modifier onlyContractOwner { | ||
require(msg.sender == owner, 'Restricted method access to only the contract owner'); | ||
_; | ||
} | ||
|
||
/** | ||
* @dev Constructor function | ||
*/ | ||
constructor (string memory _uri) ERC1155(_uri) { | ||
owner = msg.sender; | ||
} | ||
|
||
/** | ||
* @dev Only the contract owner can add a fee | ||
*/ | ||
function setFee(uint256 tokenId, address payable recipient, uint256 fee) | ||
public | ||
onlyContractOwner | ||
{ | ||
_setFee(tokenId, recipient, fee); | ||
} | ||
|
||
/** | ||
* @dev Only the contract owner can remove a fee | ||
*/ | ||
function removeFee(uint256 tokenId, address payable recipient) | ||
public | ||
onlyContractOwner | ||
{ | ||
_removeFee(tokenId, recipient); | ||
} | ||
|
||
/** | ||
* @dev Creates `quantity` new tokens for `to`, of token type `id`. | ||
*/ | ||
function mint(address to, uint256 id, uint256 quantity, bytes memory data) | ||
public | ||
virtual | ||
{ | ||
_mint(to, id, quantity, data); | ||
} | ||
|
||
/** | ||
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] variant of {mint}. | ||
*/ | ||
function mintBatch( | ||
address to, | ||
uint256[] memory ids, | ||
uint256[] memory amounts, | ||
bytes memory data | ||
) public virtual { | ||
_mintBatch(to, ids, amounts, data); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
contracts/token/ERC1155/extensions/ERC1155AirDroppable.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
//implementation of ERC1155 | ||
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; | ||
|
||
//crypto logic for merkle trees | ||
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; | ||
|
||
abstract contract ERC1155AirDroppable is ERC1155 { | ||
//token id -> merkle roots | ||
mapping(uint256 => bytes32) private _merkleRoots; | ||
|
||
function _drop(uint256 tokenId, bytes32 merkleRoot) internal { | ||
//use logic to make it immutable | ||
require(_merkleRoots[tokenId] == 0, "Merkle root is immutable"); | ||
_merkleRoots[tokenId] = merkleRoot; | ||
} | ||
|
||
/** | ||
* @dev Allows recipients to generally redeem their token | ||
*/ | ||
function redeem( | ||
address recipient, | ||
uint256 tokenId, | ||
uint256 quantity, | ||
bytes32[] calldata proof, | ||
bytes memory data | ||
) external { | ||
require( | ||
//this verifies that the recipient owns this token | ||
MerkleProof.verify( | ||
proof, | ||
_merkleRoots[tokenId], | ||
//this is the leaf hash | ||
keccak256(abi.encodePacked(recipient, tokenId, quantity)) | ||
), | ||
"Recipient does not own this token" | ||
); | ||
_mint(recipient, tokenId, quantity, data); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
//custom abstract implementation of ERC1155 | ||
import "./ERC1155Listable.sol"; | ||
|
||
abstract contract ERC1155Exchangable is ERC1155Listable { | ||
/** | ||
* @dev Allows for a sender to avail of the offer price | ||
*/ | ||
function exchange( | ||
address owner, | ||
uint256 tokenId, | ||
uint256 quantity, | ||
bytes memory data | ||
) public payable { | ||
//get listing | ||
uint256 listingAmount = _listingAmounts[tokenId][owner]; | ||
//get quantity | ||
uint256 listingQuantity = _listingQuantities[tokenId][owner]; | ||
//should be a valid listing | ||
require( | ||
listingAmount > 0 && listingQuantity > 0, | ||
'Owner token is not listed' | ||
); | ||
//quantity should be lte to the listing quantity | ||
require( | ||
quantity <= listingQuantity, | ||
'Quantity is more than what was listed' | ||
); | ||
//value should equal the listing amount | ||
require( | ||
msg.value == (listingAmount * quantity), | ||
"Amount sent does not match the listing amount" | ||
); | ||
//get the token owner | ||
address payable tokenOwner = payable(owner); | ||
|
||
//distribute payment to the token owner ... | ||
tokenOwner.transfer(msg.value); | ||
//transfer token | ||
_safeTransferFrom(owner, msg.sender, tokenId, quantity, data); | ||
|
||
//if no more available | ||
if (quantity == listingQuantity) { | ||
//delist | ||
delete _listingAmounts[tokenId][owner]; | ||
delete _listingQuantities[tokenId][owner]; | ||
//emit that something was delisted | ||
emit Delisted(owner, tokenId); | ||
} else { | ||
//otherwise, adjust the quantity | ||
_listingQuantities[tokenId][owner] -= quantity; | ||
} | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
contracts/token/ERC1155/extensions/ERC1155ExchangableFees.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
//custom abstract implementation of ERC721 | ||
import "./ERC1155TransferFees.sol"; | ||
|
||
//custom abstract implementation of ERC1155 | ||
import "./ERC1155Listable.sol"; | ||
|
||
abstract contract ERC1155ExchangableFees is ERC1155TransferFees, ERC1155Listable { | ||
/** | ||
* @dev Allows for a sender to avail of the offer price | ||
*/ | ||
function exchange( | ||
address owner, | ||
uint256 tokenId, | ||
uint256 quantity, | ||
bytes memory data | ||
) public payable { | ||
//get listing | ||
uint256 listingAmount = _listingAmounts[tokenId][owner]; | ||
//get quantity | ||
uint256 listingQuantity = _listingQuantities[tokenId][owner]; | ||
//should be a valid listing | ||
require( | ||
listingAmount > 0 && listingQuantity > 0, | ||
'Owner token is not listed' | ||
); | ||
//quantity should be lte to the listing quantity | ||
require( | ||
quantity <= listingQuantity, | ||
'Quantity is more than what was listed' | ||
); | ||
//value should equal the listing amount | ||
require( | ||
msg.value == (listingAmount * quantity), | ||
"Amount sent does not match the listing amount" | ||
); | ||
|
||
//release payments to recipients | ||
for (uint i = 0; i < _recipients[tokenId].length; i++) { | ||
// (10 eth * 2000) / 10000 = | ||
payable(_recipients[tokenId][i]).transfer( | ||
(msg.value * _fees[tokenId][_recipients[tokenId][i]]) / TOTAL_ALLOWABLE_FEES | ||
); | ||
} | ||
|
||
//get the token owner | ||
address payable tokenOwner = payable(owner); | ||
//determine the remaining fee | ||
uint256 remainingFee = TOTAL_ALLOWABLE_FEES - _totalFees[tokenId]; | ||
//send the remaining fee to the token owner | ||
tokenOwner.transfer((msg.value * remainingFee) / TOTAL_ALLOWABLE_FEES); | ||
//transfer token | ||
_safeTransferFrom(owner, msg.sender, tokenId, quantity, data); | ||
|
||
//if no more available | ||
if (quantity == listingQuantity) { | ||
//delist | ||
delete _listingAmounts[tokenId][owner]; | ||
delete _listingQuantities[tokenId][owner]; | ||
//emit that something was delisted | ||
emit Delisted(owner, tokenId); | ||
} else { | ||
//otherwise, adjust the quantity | ||
_listingQuantities[tokenId][owner] -= quantity; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
//implementation of ERC1155 | ||
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; | ||
|
||
abstract contract ERC1155Listable is ERC1155 { | ||
//allow others to watch for listed tokens | ||
event Listed( | ||
address indexed owner, | ||
uint256 indexed tokenId, | ||
uint256[2] indexed listing | ||
); | ||
//allow others to watch for delisted tokens | ||
event Delisted(address indexed owner, uint256 indexed tokenId); | ||
|
||
//map for all listings | ||
//token id -> recipient -> amount | ||
mapping(uint256 => mapping(address => uint256)) internal _listingAmounts; | ||
|
||
//map for all listings | ||
//token id -> recipient -> quantity | ||
mapping(uint256 => mapping(address => uint256)) internal _listingQuantities; | ||
|
||
struct Listing { | ||
address owner; | ||
uint256 tokenId; | ||
uint256 amount; | ||
uint256 quantity; | ||
} | ||
|
||
/** | ||
* @dev Allows token owners to list their tokens for sale | ||
*/ | ||
function list(uint256 tokenId, uint256 amount, uint256 quantity) public { | ||
uint256 balance = balanceOf(msg.sender, tokenId); | ||
//error if the sender is not the owner | ||
// even the contract owner cannot list a token | ||
require(balance > 0, "Only the token owner can list a token"); | ||
//error if the balance is less than the quantity to be listed | ||
require(quantity <= balance, "Token owner listing more than available"); | ||
//add the listing | ||
//if the listing exists, update | ||
_listingAmounts[tokenId][msg.sender] = amount; | ||
_listingQuantities[tokenId][msg.sender] = quantity; | ||
|
||
//emit that something was listed | ||
emit Listed(msg.sender, tokenId, [amount, quantity]); | ||
} | ||
|
||
/** | ||
* @dev Allows token owners to remove their token sale listing | ||
*/ | ||
function delist(uint256 tokenId) public { | ||
//error if the sender is not the owner | ||
// even the contract owner cannot delist a token | ||
require( | ||
balanceOf(msg.sender, tokenId) > 0, | ||
"Only the token owner can delist a token" | ||
); | ||
//remove the listing | ||
delete _listingAmounts[tokenId][msg.sender]; | ||
delete _listingQuantities[tokenId][msg.sender]; | ||
//emit that something was delisted | ||
emit Delisted(msg.sender, tokenId); | ||
} | ||
|
||
/** | ||
* @dev Returns the amount being sold for | ||
*/ | ||
function getListing(address owner, uint256 tokenId) | ||
public | ||
view | ||
returns(Listing memory) | ||
{ | ||
return Listing( | ||
owner, | ||
tokenId, | ||
_listingAmounts[tokenId][msg.sender], | ||
_listingQuantities[tokenId][msg.sender] | ||
); | ||
} | ||
} |
Oops, something went wrong.