diff --git a/examples/DemosForIstanbul/Demo1/DiLithiumERC20.sol b/examples/DemosForIstanbul/Demo1/DiLithiumERC20.sol new file mode 100644 index 0000000..9c7df8f --- /dev/null +++ b/examples/DemosForIstanbul/Demo1/DiLithiumERC20.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +interface ISequentialMint { + function mintUsingSequentialTokenId() external; + function balanceOf(address owner) view external returns (uint256); +} + +contract DiLithiumToken is ERC20, Ownable +{ + address private NFTLock = 0x910179fa965CB822c95BF7c21a1846A1B6DE1D99; + mapping(address => bool) private _canSpend; + + constructor() ERC20("STL Di-lithium Power", "STLD") + { + + } + + function addCanSpend(address canSpend) public onlyOwner + { + _canSpend[canSpend] = true; + } + + function _spendAllowance(address owner, address spender, uint256 amount) internal override virtual { + if (!_canSpend[spender]) //allow if allowed spender + { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance != type(uint256).max) { + require(currentAllowance >= amount, "ERC20: insufficient allowance"); + unchecked { + _approve(owner, spender, currentAllowance - amount); + } + } + } + } + + function transferFrom(address from, address to, uint256 amount) public override returns (bool) { + address spender = _msgSender(); + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + emit Transfer(from, to, amount); + return true; + } + + function mint() public + { + ISequentialMint nftControl = ISequentialMint(NFTLock); + //Get Balance + uint256 userBal = nftControl.balanceOf(msg.sender); + //only allow minting if user holds the NFT + require (userBal > 0, "You don't hold the NFT"); + + _mint(msg.sender, 20 * (10 ** 18)); + } +} \ No newline at end of file diff --git a/examples/DemosForIstanbul/Demo1/GenericNFTWithScript.sol b/examples/DemosForIstanbul/Demo1/GenericNFTWithScript.sol new file mode 100644 index 0000000..8fe6fb3 --- /dev/null +++ b/examples/DemosForIstanbul/Demo1/GenericNFTWithScript.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import "@openzeppelin/contracts/utils/Counters.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import { ERC5169 } from "stl-contracts/ERC/ERC5169.sol"; + +contract GenericNFT is ERC721Enumerable, Ownable { + using Strings for uint256; + using Counters for Counters.Counter; + + Counters.Counter public _tokenIdCounter; + uint private _maxSupply = 10000; + string private _scriptURI; + + string private constant _metadata = "https://metadata.artlab.xyz/01892bef-5488-84a9-a800-92d55e4e534e/"; + + address private easContractAddress; + + constructor() ERC721("TokenScript Demo #1", "TSD") { + _tokenIdCounter.increment(); + _scriptURI = "ipfs://QmdkzDdiAx7cqWU2XgGhgzgqRr4LRtjYXbvLZ5viSDajkB"; + mintUsingSequentialTokenId(); + } + + function getChainId() public view returns (uint256 chainId) { + chainId = block.chainid; + } + + function scriptURI() public view returns (string memory) { + return _scriptURI; + } + + function updateScriptURI(string memory newScript) public onlyOwner { + _scriptURI = newScript; + } + + function contractURI() public pure returns (string memory) { + return "ipfs://QmR4Ti6huhEKh3pWQZ8tRuSGJaB7FvWuRDVzWYRmZsQAjF"; + } + + function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { + require(_exists(tokenId), "tokenURI: URI query for nonexistent token"); + return string(abi.encodePacked(_metadata, tokenId.toString())); + } + + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Enumerable) returns (bool) { + return + ERC721Enumerable.supportsInterface(interfaceId); + } + + function mintUsingSequentialTokenId() public returns (uint256 tokenId) { + tokenId = _tokenIdCounter.current(); + require(tokenId < _maxSupply, "Hit upper mint limit"); + _mint(msg.sender, tokenId); + _tokenIdCounter.increment(); + } + + function burnToken(uint256 tokenId) public { + require(_exists(tokenId), "burn: nonexistent token"); + require(ownerOf(tokenId) == msg.sender || msg.sender == owner(), "Token must be owned"); + _burn(tokenId); + } + +} \ No newline at end of file diff --git a/examples/DemosForIstanbul/Demo1/demotoken1.xml b/examples/DemosForIstanbul/Demo1/demotoken1.xml new file mode 100644 index 0000000..0f46df1 --- /dev/null +++ b/examples/DemosForIstanbul/Demo1/demotoken1.xml @@ -0,0 +1,48 @@ + + + + + TokenScript Demo #1 Token + TokenScript Demo #1 Tokens + + + Token #1 de demostración de TokenScript + Token #1 de demostración de TokenScript + + + + + + 0x910179fa965CB822c95BF7c21a1846A1B6DE1D99 + + + 0x62130D3EC0A74D797BD3B1645222843a601F92Ae + + + + + + + + + + + + Mint Rewards + + + + + + + + + + diff --git a/examples/DemosForIstanbul/Demo2/MechNFT.sol b/examples/DemosForIstanbul/Demo2/MechNFT.sol new file mode 100644 index 0000000..f3227d8 --- /dev/null +++ b/examples/DemosForIstanbul/Demo2/MechNFT.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import "@openzeppelin/contracts/utils/Counters.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +interface IERC20Check { + function balanceOf(address owner) view external returns (uint256); +} + +contract MechNFT is ERC721Enumerable, Ownable { + using Strings for uint256; + using Counters for Counters.Counter; + + Counters.Counter public _tokenIdCounter; + uint private _maxSupply = 10000; + string private _scriptURI; + + address private STLTokens = 0x62130D3EC0A74D797BD3B1645222843a601F92Ae; + + string private constant _metadata = "https://ipfs.io/ipfs/Qmcob1MaPTXUZt5MztHEgsYhrf7R6G7wV8hpcweL8nEfgU/meka/"; + + address private easContractAddress; + + constructor() ERC721("TokenScript Demo #2", "TSD2") { + _tokenIdCounter.increment(); + _scriptURI = ""; + mintUsingSequentialTokenId(); + } + + function updatePayment(address newPTokens) public onlyOwner + { + STLTokens = newPTokens; + } + + function getChainId() public view returns (uint256 chainId) { + chainId = block.chainid; + } + + function scriptURI() public view returns (string memory) { + return _scriptURI; + } + + function updateScriptURI(string memory newScript) public onlyOwner { + _scriptURI = newScript; + } + + function contractURI() public pure returns (string memory) { + return "ipfs://QmR4Ti6huhEKh3pWQZ8tRuSGJaB7FvWuRDVzWYRmZsQAjF"; + } + + function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { + require(_exists(tokenId), "tokenURI: URI query for nonexistent token"); + return string(abi.encodePacked(_metadata, tokenId.toString())); + } + + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Enumerable) returns (bool) { + return + ERC721Enumerable.supportsInterface(interfaceId); + } + + function mintUsingSequentialTokenId() public returns (uint256 tokenId) { + tokenId = _tokenIdCounter.current(); + require(tokenId < _maxSupply, "Hit upper mint limit"); + _mint(msg.sender, tokenId); + _tokenIdCounter.increment(); + } + + function burnToken(uint256 tokenId) public { + require(_exists(tokenId), "burn: nonexistent token"); + require(ownerOf(tokenId) == msg.sender || msg.sender == owner(), "Token must be owned"); + _burn(tokenId); + } + + function canMint() public view returns (bool) { + IERC20Check nftControl = IERC20Check(STLTokens); + //Get Balance + uint256 userBal = nftControl.balanceOf(msg.sender); + //only allow minting if user holds the NFT + if (userBal >= 20 * (10 ** 18)) + { + return true; + } + else + { + return false; + } + } +} \ No newline at end of file diff --git a/examples/DemosForIstanbul/Demo2/SecretNFT.sol b/examples/DemosForIstanbul/Demo2/SecretNFT.sol new file mode 100644 index 0000000..ef908c1 --- /dev/null +++ b/examples/DemosForIstanbul/Demo2/SecretNFT.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import "@openzeppelin/contracts/utils/Counters.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +interface IERC20Tokens { + function balanceOf(address owner) view external returns (uint256); + function transferFrom(address from, address to, uint256 amount) external returns (bool); +} + +interface ITokenCheck { + function balanceOf(address owner) view external returns (uint256); +} + +contract SecretNFT is ERC721Enumerable, Ownable { + using Strings for uint256; + using Counters for Counters.Counter; + + Counters.Counter public _tokenIdCounter; + uint private _maxSupply = 10000; + string private _scriptURI; + + string constant private _element1 = "{ " + "\"name\": \""; + string constant private _element2 = "\", \"image\":" + "\"ipfs://QmYDvPAXtiJg7s8JdRBSLWdgSphQdac8j1YuQNNxcGE1hg/"; + string constant private _element3 = ".png\" }"; + + mapping(uint256 => string) private _names; + + address private _STLTokens = 0x62130D3EC0A74D797BD3B1645222843a601F92Ae; + address private _MintingToken = 0xc6906a1D878B9e09c80964dd60b52aC92E1113E6; + uint256 private _mintCost = 20 * (10 ** 18); + + address private easContractAddress; + + constructor() ERC721("Secret TokenScript Token", "STT") { + _tokenIdCounter.increment(); + _scriptURI = ""; + } + + function updatePayment(address newPTokens) public onlyOwner + { + _STLTokens = newPTokens; + } + + function updateMinting(address newMToken) public onlyOwner + { + _MintingToken = newMToken; + } + + function getChainId() public view returns (uint256 chainId) { + chainId = block.chainid; + } + + function scriptURI() public view returns (string memory) { + return _scriptURI; + } + + function updateScriptURI(string memory newScript) public onlyOwner { + _scriptURI = newScript; + } + + function contractURI() public pure returns (string memory) { + return "ipfs://QmR4Ti6huhEKh3pWQZ8tRuSGJaB7FvWuRDVzWYRmZsQAjF"; + } + + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Enumerable) returns (bool) { + return + ERC721Enumerable.supportsInterface(interfaceId); + } + + function mintWithName(string memory newName) public returns (uint256 tokenId) + { + //1. check we have enough coins + //2. check we have the NFT + tokenId = _tokenIdCounter.current(); + require (canMint(msg.sender), "You don't have permission to mint"); + require(tokenId < _maxSupply, "Hit upper mint limit"); + + //3. Spend coins + IERC20Tokens spendTokens = IERC20Tokens(_STLTokens); + if (spendTokens.transferFrom(msg.sender, address(this), _mintCost)) + { + //spent the tokens, now mint the new token and write the metadata + _mint(msg.sender, tokenId); + _names[tokenId] = newName; + _tokenIdCounter.increment(); + } + } + + function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { + require(_exists(tokenId), "tokenURI: URI query for nonexistent token"); + + return string(abi.encodePacked(_element1, _names[tokenId], _element2, tokenId.toString() + , _element3)); + } + + function burnToken(uint256 tokenId) public { + require(_exists(tokenId), "burn: nonexistent token"); + require(ownerOf(tokenId) == msg.sender || msg.sender == owner(), "Token must be owned"); + _burn(tokenId); + } + + function canMint(address sender) public view returns (bool) { + ITokenCheck nftControl = ITokenCheck(_STLTokens); + //Get Balance + uint256 userBal = nftControl.balanceOf(sender); + //only allow minting if user holds the NFT + if (userBal < _mintCost) + { + return false; + } + + //does own the minting token? + ITokenCheck mintingNFT = ITokenCheck(_MintingToken); + userBal = mintingNFT.balanceOf(sender); + if (userBal == 0) + { + return false; + } + else + { + return true; + } + } +} \ No newline at end of file diff --git a/examples/DemosForIstanbul/Demo2/demotoken2.xml b/examples/DemosForIstanbul/Demo2/demotoken2.xml new file mode 100644 index 0000000..145b6a0 --- /dev/null +++ b/examples/DemosForIstanbul/Demo2/demotoken2.xml @@ -0,0 +1,115 @@ + + + + + TokenScript Demo #2 Token + TokenScript Demo #2 Tokens + + + Token #2 de demostración de TokenScript + Token #2 de demostración de TokenScript + + + + + + 0xc6906a1D878B9e09c80964dd60b52aC92E1113E6 + + + 0x62130D3EC0A74D797BD3B1645222843a601F92Ae + + + 0x8D975a1404603314886B7Ca9d3fC711B5eEf23A8 + + + + + + + + + + Cannot Mint + + + + + + + Mint Secret + + + + 1.3.6.1.4.1.1466.115.121.1.26 + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.3.6.1.4.1.1466.115.121.1.7 + + + + + + + + + \ No newline at end of file