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