polkamarkets-js 3.4.0 → 3.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abis/PredictionMarketV3Querier.json +1 -1
- package/contracts/PredictionMarketV3Querier.sol +4 -2
- package/package.json +1 -1
- package/src/models/PredictionMarketV3Contract.js +51 -17
- package/abis/AddAdminToLand.json +0 -1
- package/abis/ClaimMerkleRoot.json +0 -1
- package/abis/CreateLand.json +0 -1
- package/abis/CreateMarkets.json +0 -1
- package/abis/DeployContracts.json +0 -1
- package/abis/DeployMerkleRewardsDistributor.json +0 -1
- package/abis/DeployToken.json +0 -1
- package/abis/DeployUSDT.json +0 -1
- package/abis/MintTokens.json +0 -1
- package/abis/PublishMerkleRoot.json +0 -1
- package/abis/ResolveMarket.json +0 -1
- package/abis/TradeMarket.json +0 -1
- package/abis/USDT.json +0 -1
- package/lib/openzeppelin-contracts/contracts/mocks/docs/ERC20WithAutoMinerReward.sol +0 -22
- package/lib/openzeppelin-contracts/contracts/mocks/docs/ERC4626Fees.sol +0 -109
- package/lib/openzeppelin-contracts/contracts/mocks/docs/MyNFT.sol +0 -9
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintBase.sol +0 -25
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintMissing.sol +0 -24
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintOnlyRole.sol +0 -23
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlModified.sol +0 -14
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessManagedERC20MintBase.sol +0 -16
- package/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/MyContractOwnable.sol +0 -17
- package/lib/openzeppelin-contracts/contracts/mocks/docs/account/MyAccountERC7702.sol +0 -20
- package/lib/openzeppelin-contracts/contracts/mocks/docs/account/MyFactoryAccount.sol +0 -37
- package/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyGovernor.sol +0 -80
- package/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyToken.sol +0 -21
- package/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyTokenTimestampBased.sol +0 -32
- package/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyTokenWrapped.sol +0 -28
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC1155/GameItems.sol +0 -21
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC1155/MyERC115HolderContract.sol +0 -7
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC20/GLDToken.sol +0 -11
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol +0 -26
- package/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC721/GameItem.sol +0 -19
- package/lib/openzeppelin-contracts/contracts/mocks/docs/utilities/Base64NFT.sol +0 -27
- package/lib/openzeppelin-contracts/contracts/mocks/docs/utilities/Multicall.sol +0 -15
- package/lib/openzeppelin-contracts/docs/README.md +0 -16
- package/lib/openzeppelin-contracts/docs/antora.yml +0 -7
- package/lib/openzeppelin-contracts/docs/config.js +0 -21
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-control-multiple.svg +0 -97
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-manager-functions.svg +0 -47
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-manager.svg +0 -99
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-3a.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-3b.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-6.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-deposit.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-mint.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-linear.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-loglog.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-loglogext.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/tally-exec.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/images/tally-vote.png +0 -0
- package/lib/openzeppelin-contracts/docs/modules/ROOT/nav.adoc +0 -29
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/access-control.adoc +0 -288
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/account-abstraction.adoc +0 -100
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/accounts.adoc +0 -354
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/backwards-compatibility.adoc +0 -50
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/eoa-delegation.adoc +0 -143
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc1155.adoc +0 -118
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc20-supply.adoc +0 -71
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc20.adoc +0 -67
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc4626.adoc +0 -214
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc6909.adoc +0 -47
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc721.adoc +0 -58
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/extending-contracts.adoc +0 -51
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/faq.adoc +0 -13
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/governance.adoc +0 -239
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/index.adoc +0 -70
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/multisig.adoc +0 -306
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/tokens.adoc +0 -31
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/upgradeable.adoc +0 -77
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/utilities.adoc +0 -591
- package/lib/openzeppelin-contracts/docs/modules/ROOT/pages/wizard.adoc +0 -15
- package/lib/openzeppelin-contracts/docs/templates/contract.hbs +0 -141
- package/lib/openzeppelin-contracts/docs/templates/helpers.js +0 -46
- package/lib/openzeppelin-contracts/docs/templates/page.hbs +0 -4
- package/lib/openzeppelin-contracts/docs/templates/properties.js +0 -88
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/ERC20WithAutoMinerRewardUpgradeable.sol +0 -28
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/ERC4626FeesUpgradeable.sol +0 -115
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/MyNFTUpgradeable.sol +0 -14
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/access-control/AccessControlERC20MintBaseUpgradeable.sol +0 -31
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/access-control/AccessControlERC20MintMissingUpgradeable.sol +0 -30
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/access-control/AccessControlERC20MintOnlyRoleUpgradeable.sol +0 -29
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/access-control/AccessControlModifiedUpgradeable.sol +0 -20
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/access-control/AccessManagedERC20MintBaseUpgradeable.sol +0 -22
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/access-control/MyContractOwnableUpgradeable.sol +0 -22
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/account/MyAccountERC7702Upgradeable.sol +0 -26
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/account/MyFactoryAccountUpgradeable.sol +0 -42
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/governance/MyGovernorUpgradeable.sol +0 -92
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/governance/MyTokenTimestampBasedUpgradeable.sol +0 -39
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/governance/MyTokenUpgradeable.sol +0 -28
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/governance/MyTokenWrappedUpgradeable.sol +0 -39
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/token/ERC1155/GameItemsUpgradeable.sol +0 -27
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/token/ERC1155/MyERC115HolderContractUpgradeable.sol +0 -13
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/token/ERC20/GLDTokenUpgradeable.sol +0 -17
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/token/ERC6909/ERC6909GameItemsUpgradeable.sol +0 -31
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/token/ERC721/GameItemUpgradeable.sol +0 -24
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/utilities/Base64NFTUpgradeable.sol +0 -32
- package/lib/openzeppelin-contracts-upgradeable/contracts/mocks/docs/utilities/MulticallUpgradeable.sol +0 -21
- package/lib/openzeppelin-contracts-upgradeable/docs/README.md +0 -16
- package/lib/openzeppelin-contracts-upgradeable/docs/antora.yml +0 -7
- package/lib/openzeppelin-contracts-upgradeable/docs/config.js +0 -21
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/access-control-multiple.svg +0 -97
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/access-manager-functions.svg +0 -47
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/access-manager.svg +0 -99
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-attack-3a.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-attack-3b.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-attack-6.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-attack.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-deposit.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-mint.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-rate-linear.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-rate-loglog.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/erc4626-rate-loglogext.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/tally-exec.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/images/tally-vote.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/nav.adoc +0 -29
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/access-control.adoc +0 -288
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/account-abstraction.adoc +0 -100
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/accounts.adoc +0 -354
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/backwards-compatibility.adoc +0 -50
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/eoa-delegation.adoc +0 -143
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/erc1155.adoc +0 -118
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/erc20-supply.adoc +0 -71
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/erc20.adoc +0 -67
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/erc4626.adoc +0 -214
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/erc6909.adoc +0 -47
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/erc721.adoc +0 -58
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/extending-contracts.adoc +0 -51
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/faq.adoc +0 -13
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/governance.adoc +0 -239
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/index.adoc +0 -70
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/multisig.adoc +0 -306
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/tokens.adoc +0 -31
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/upgradeable.adoc +0 -77
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/utilities.adoc +0 -591
- package/lib/openzeppelin-contracts-upgradeable/docs/modules/ROOT/pages/wizard.adoc +0 -15
- package/lib/openzeppelin-contracts-upgradeable/docs/templates/contract.hbs +0 -141
- package/lib/openzeppelin-contracts-upgradeable/docs/templates/helpers.js +0 -46
- package/lib/openzeppelin-contracts-upgradeable/docs/templates/page.hbs +0 -4
- package/lib/openzeppelin-contracts-upgradeable/docs/templates/properties.js +0 -88
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/ERC20WithAutoMinerReward.sol +0 -22
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/ERC4626Fees.sol +0 -109
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/MyNFT.sol +0 -9
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintBase.sol +0 -25
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintMissing.sol +0 -24
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlERC20MintOnlyRole.sol +0 -23
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessControlModified.sol +0 -14
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/AccessManagedERC20MintBase.sol +0 -16
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/access-control/MyContractOwnable.sol +0 -17
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/account/MyAccountERC7702.sol +0 -20
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/account/MyFactoryAccount.sol +0 -37
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyGovernor.sol +0 -80
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyToken.sol +0 -21
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyTokenTimestampBased.sol +0 -32
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/governance/MyTokenWrapped.sol +0 -28
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC1155/GameItems.sol +0 -21
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC1155/MyERC115HolderContract.sol +0 -7
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC20/GLDToken.sol +0 -11
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol +0 -26
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/token/ERC721/GameItem.sol +0 -19
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/utilities/Base64NFT.sol +0 -27
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/mocks/docs/utilities/Multicall.sol +0 -15
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/README.md +0 -16
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/antora.yml +0 -7
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/config.js +0 -21
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-control-multiple.svg +0 -97
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-manager-functions.svg +0 -47
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/access-manager.svg +0 -99
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-3a.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-3b.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack-6.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-attack.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-deposit.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-mint.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-linear.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-loglog.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/erc4626-rate-loglogext.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/tally-exec.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/images/tally-vote.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/nav.adoc +0 -29
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/access-control.adoc +0 -288
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/account-abstraction.adoc +0 -100
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/accounts.adoc +0 -354
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/backwards-compatibility.adoc +0 -50
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/eoa-delegation.adoc +0 -143
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc1155.adoc +0 -118
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc20-supply.adoc +0 -71
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc20.adoc +0 -67
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc4626.adoc +0 -214
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc6909.adoc +0 -47
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/erc721.adoc +0 -58
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/extending-contracts.adoc +0 -51
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/faq.adoc +0 -13
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/governance.adoc +0 -239
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/index.adoc +0 -70
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/multisig.adoc +0 -306
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/tokens.adoc +0 -31
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/upgradeable.adoc +0 -77
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/utilities.adoc +0 -591
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/modules/ROOT/pages/wizard.adoc +0 -15
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/templates/contract.hbs +0 -141
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/templates/helpers.js +0 -46
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/templates/page.hbs +0 -4
- package/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/docs/templates/properties.js +0 -88
- package/lib/openzeppelin-contracts-upgradeable.git/docs/antora.yml +0 -6
- package/lib/openzeppelin-contracts-upgradeable.git/docs/config.js +0 -21
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/images/tally-exec.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/images/tally-vote.png +0 -0
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/nav.adoc +0 -23
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/access-control.adoc +0 -217
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/crosschain.adoc +0 -210
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/crowdsales.adoc +0 -11
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/drafts.adoc +0 -19
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/erc1155.adoc +0 -153
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/erc20-supply.adoc +0 -113
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/erc20.adoc +0 -85
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/erc721.adoc +0 -90
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/erc777.adoc +0 -73
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/extending-contracts.adoc +0 -129
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/governance.adoc +0 -321
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/index.adoc +0 -63
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/releases-stability.adoc +0 -85
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/tokens.adoc +0 -32
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/upgradeable.adoc +0 -73
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/utilities.adoc +0 -190
- package/lib/openzeppelin-contracts-upgradeable.git/docs/modules/ROOT/pages/wizard.adoc +0 -15
- package/lib/openzeppelin-contracts-upgradeable.git/docs/templates/contract.hbs +0 -85
- package/lib/openzeppelin-contracts-upgradeable.git/docs/templates/helpers.js +0 -46
- package/lib/openzeppelin-contracts-upgradeable.git/docs/templates/page.hbs +0 -4
- package/lib/openzeppelin-contracts-upgradeable.git/docs/templates/properties.js +0 -49
- package/lib/openzeppelin-contracts.git/docs/antora.yml +0 -6
- package/lib/openzeppelin-contracts.git/docs/config.js +0 -21
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/images/tally-exec.png +0 -0
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/images/tally-vote.png +0 -0
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/nav.adoc +0 -23
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/access-control.adoc +0 -217
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/crosschain.adoc +0 -210
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/crowdsales.adoc +0 -11
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/drafts.adoc +0 -19
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/erc1155.adoc +0 -153
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/erc20-supply.adoc +0 -113
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/erc20.adoc +0 -85
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/erc721.adoc +0 -90
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/erc777.adoc +0 -73
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/extending-contracts.adoc +0 -129
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/governance.adoc +0 -321
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/index.adoc +0 -63
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/releases-stability.adoc +0 -85
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/tokens.adoc +0 -32
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/upgradeable.adoc +0 -73
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/utilities.adoc +0 -190
- package/lib/openzeppelin-contracts.git/docs/modules/ROOT/pages/wizard.adoc +0 -15
- package/lib/openzeppelin-contracts.git/docs/templates/contract.hbs +0 -85
- package/lib/openzeppelin-contracts.git/docs/templates/helpers.js +0 -46
- package/lib/openzeppelin-contracts.git/docs/templates/page.hbs +0 -4
- package/lib/openzeppelin-contracts.git/docs/templates/properties.js +0 -49
- package/lib/reality-eth-monorepo/packages/docs/Audit_Reality_v3_202108.pdf +0 -0
- package/lib/reality-eth-monorepo/packages/docs/Makefile +0 -20
- package/lib/reality-eth-monorepo/packages/docs/arbitrators.rst +0 -85
- package/lib/reality-eth-monorepo/packages/docs/audit.rst +0 -12
- package/lib/reality-eth-monorepo/packages/docs/audit_v2.rst +0 -249
- package/lib/reality-eth-monorepo/packages/docs/audit_v2_ERC20.rst +0 -1075
- package/lib/reality-eth-monorepo/packages/docs/audit_v3.rst +0 -70
- package/lib/reality-eth-monorepo/packages/docs/conf.py +0 -155
- package/lib/reality-eth-monorepo/packages/docs/contract_explanation.rst +0 -82
- package/lib/reality-eth-monorepo/packages/docs/contracts.rst +0 -277
- package/lib/reality-eth-monorepo/packages/docs/dapp.rst +0 -126
- package/lib/reality-eth-monorepo/packages/docs/dapp_links.rst +0 -67
- package/lib/reality-eth-monorepo/packages/docs/fees.rst +0 -89
- package/lib/reality-eth-monorepo/packages/docs/index.rst +0 -26
- package/lib/reality-eth-monorepo/packages/docs/javascript.rst +0 -142
- package/lib/reality-eth-monorepo/packages/docs/make.bat +0 -36
- package/lib/reality-eth-monorepo/packages/docs/question_box.png +0 -0
- package/lib/reality-eth-monorepo/packages/docs/requirements.txt +0 -24
- package/lib/reality-eth-monorepo/packages/docs/whitepaper.rst +0 -165
- package/script/UpdateMarket.s.sol +0 -56
- package/scripts/AddAdminToLand.s.sol +0 -29
- package/scripts/ClaimMerkleRoot.s.sol +0 -34
- package/scripts/CreateLand.s.sol +0 -28
- package/scripts/CreateMarkets.s.sol +0 -71
- package/scripts/DeployContracts.s.sol +0 -94
- package/scripts/DeployMerkleRewardsDistributor.s.sol +0 -27
- package/scripts/DeployToken.s.sol +0 -17
- package/scripts/DeployUSDT.s.sol +0 -24
- package/scripts/MintTokens.s.sol +0 -21
- package/scripts/PublishMerkleRoot.s.sol +0 -50
- package/scripts/ResolveMarket.s.sol +0 -23
- package/scripts/TradeMarket.s.sol +0 -28
- package/scripts/UpdateMarket.s.sol +0 -55
- package/test/UpdateTest.t.sol +0 -55
- package/test/WhaleTest.t.sol +0 -188
- package/tooling/docs/jsdoc.json +0 -6
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
= ERC-1155
|
|
2
|
-
|
|
3
|
-
ERC-1155 is a novel token standard that aims to take the best from previous standards to create a xref:tokens.adoc#different-kinds-of-tokens[*fungibility-agnostic*] and *gas-efficient* xref:tokens.adoc#but_first_coffee_a_primer_on_token_contracts[token contract].
|
|
4
|
-
|
|
5
|
-
TIP: ERC-1155 draws ideas from all of xref:erc20.adoc[ERC-20], xref:erc721.adoc[ERC-721], and https://eips.ethereum.org/EIPS/eip-777[ERC-777]. If you're unfamiliar with those standards, head to their guides before moving on.
|
|
6
|
-
|
|
7
|
-
[[multi-token-standard]]
|
|
8
|
-
== Multi Token Standard
|
|
9
|
-
|
|
10
|
-
The distinctive feature of ERC-1155 is that it uses a single smart contract to represent multiple tokens at once. This is why its xref:api:token/ERC1155.adoc#IERC1155-balanceOf-address-uint256-[`balanceOf`] function differs from ERC-20's and ERC-777's: it has an additional `id` argument for the identifier of the token that you want to query the balance of.
|
|
11
|
-
|
|
12
|
-
This is similar to how ERC-721 does things, but in that standard a token `id` has no concept of balance: each token is non-fungible and exists or doesn't. The ERC-721 xref:api:token/ERC721.adoc#IERC721-balanceOf-address-[`balanceOf`] function refers to _how many different tokens_ an account has, not how many of each. On the other hand, in ERC-1155 accounts have a distinct balance for each token `id`, and non-fungible tokens are implemented by simply minting a single one of them.
|
|
13
|
-
|
|
14
|
-
This approach leads to massive gas savings for projects that require multiple tokens. Instead of deploying a new contract for each token type, a single ERC-1155 token contract can hold the entire system state, reducing deployment costs and complexity.
|
|
15
|
-
|
|
16
|
-
[[batch-operations]]
|
|
17
|
-
== Batch Operations
|
|
18
|
-
|
|
19
|
-
Because all state is held in a single contract, it is possible to operate over multiple tokens in a single transaction very efficiently. The standard provides two functions, xref:api:token/ERC1155.adoc#IERC1155-balanceOfBatch-address---uint256---[`balanceOfBatch`] and xref:api:token/ERC1155.adoc#IERC1155-safeBatchTransferFrom-address-address-uint256---uint256---bytes-[`safeBatchTransferFrom`], that make querying multiple balances and transferring multiple tokens simpler and less gas-intensive.
|
|
20
|
-
|
|
21
|
-
In the spirit of the standard, we've also included batch operations in the non-standard functions, such as xref:api:token/ERC1155.adoc#ERC1155-_mintBatch-address-uint256---uint256---bytes-[`_mintBatch`].
|
|
22
|
-
|
|
23
|
-
== Constructing an ERC-1155 Token Contract
|
|
24
|
-
|
|
25
|
-
We'll use ERC-1155 to track multiple items in our game, which will each have their own unique attributes. We mint all items to the deployer of the contract, which we can later transfer to players. Players are free to keep their tokens or trade them with other people as they see fit, as they would any other asset on the blockchain!
|
|
26
|
-
|
|
27
|
-
For simplicity, we will mint all items in the constructor, but you could add minting functionality to the contract to mint on demand to players.
|
|
28
|
-
|
|
29
|
-
TIP: For an overview of minting mechanisms, check out xref:erc20-supply.adoc[Creating ERC-20 Supply].
|
|
30
|
-
|
|
31
|
-
Here's what a contract for tokenized items might look like:
|
|
32
|
-
|
|
33
|
-
[source,solidity]
|
|
34
|
-
----
|
|
35
|
-
include::api:example$token/ERC1155/GameItems.sol[]
|
|
36
|
-
----
|
|
37
|
-
|
|
38
|
-
Note that for our Game Items, Gold is a fungible token whilst Thor's Hammer is a non-fungible token as we minted only one.
|
|
39
|
-
|
|
40
|
-
The xref:api:token/ERC1155.adoc#ERC1155[`ERC1155`] contract includes the optional extension xref:api:token/ERC1155.adoc#IERC1155MetadataURI[`IERC1155MetadataURI`]. That's where the xref:api:token/ERC1155.adoc#IERC1155MetadataURI-uri-uint256-[`uri`] function comes from: we use it to retrieve the metadata uri.
|
|
41
|
-
|
|
42
|
-
Also note that, unlike ERC-20, ERC-1155 lacks a `decimals` field, since each token is distinct and cannot be partitioned.
|
|
43
|
-
|
|
44
|
-
Once deployed, we will be able to query the deployer’s balance:
|
|
45
|
-
[source,javascript]
|
|
46
|
-
----
|
|
47
|
-
> gameItems.balanceOf(deployerAddress,3)
|
|
48
|
-
1000000000
|
|
49
|
-
----
|
|
50
|
-
|
|
51
|
-
We can transfer items to player accounts:
|
|
52
|
-
[source,javascript]
|
|
53
|
-
----
|
|
54
|
-
> gameItems.safeTransferFrom(deployerAddress, playerAddress, 2, 1, "0x0")
|
|
55
|
-
> gameItems.balanceOf(playerAddress, 2)
|
|
56
|
-
1
|
|
57
|
-
> gameItems.balanceOf(deployerAddress, 2)
|
|
58
|
-
0
|
|
59
|
-
----
|
|
60
|
-
|
|
61
|
-
We can also batch transfer items to player accounts and get the balance of batches:
|
|
62
|
-
[source,javascript]
|
|
63
|
-
----
|
|
64
|
-
> gameItems.safeBatchTransferFrom(deployerAddress, playerAddress, [0,1,3,4], [50,100,1,1], "0x0")
|
|
65
|
-
> gameItems.balanceOfBatch([playerAddress,playerAddress,playerAddress,playerAddress,playerAddress], [0,1,2,3,4])
|
|
66
|
-
[50,100,1,1,1]
|
|
67
|
-
----
|
|
68
|
-
|
|
69
|
-
The metadata uri can be obtained:
|
|
70
|
-
|
|
71
|
-
[source,javascript]
|
|
72
|
-
----
|
|
73
|
-
> gameItems.uri(2)
|
|
74
|
-
"https://game.example/api/item/{id}.json"
|
|
75
|
-
----
|
|
76
|
-
|
|
77
|
-
The `uri` can include the string `++{id}++` which clients must replace with the actual token ID, in lowercase hexadecimal (with no 0x prefix) and leading zero padded to 64 hex characters.
|
|
78
|
-
|
|
79
|
-
For token ID `2` and uri `++https://game.example/api/item/{id}.json++` clients would replace `++{id}++` with `0000000000000000000000000000000000000000000000000000000000000002` to retrieve JSON at `https://game.example/api/item/0000000000000000000000000000000000000000000000000000000000000002.json`.
|
|
80
|
-
|
|
81
|
-
The JSON document for token ID 2 might look something like:
|
|
82
|
-
|
|
83
|
-
[source,json]
|
|
84
|
-
----
|
|
85
|
-
{
|
|
86
|
-
"name": "Thor's hammer",
|
|
87
|
-
"description": "Mjölnir, the legendary hammer of the Norse god of thunder.",
|
|
88
|
-
"image": "https://game.example/item-id-8u5h2m.png",
|
|
89
|
-
"strength": 20
|
|
90
|
-
}
|
|
91
|
-
----
|
|
92
|
-
|
|
93
|
-
For more information about the metadata JSON Schema, check out the https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md#erc-1155-metadata-uri-json-schema[ERC-1155 Metadata URI JSON Schema].
|
|
94
|
-
|
|
95
|
-
NOTE: You'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game!
|
|
96
|
-
|
|
97
|
-
TIP: If you'd like to put all item information on-chain, you can extend ERC-721 to do so (though it will be rather costly) by providing a xref:utilities.adoc#base64[`Base64`] Data URI with the JSON schema encoded. You could also leverage IPFS to store the URI information, but these techniques are out of the scope of this overview guide
|
|
98
|
-
|
|
99
|
-
[[sending-to-contracts]]
|
|
100
|
-
== Sending Tokens to Contracts
|
|
101
|
-
|
|
102
|
-
A key difference when using xref:api:token/ERC1155.adoc#IERC1155-safeTransferFrom-address-address-uint256-uint256-bytes-[`safeTransferFrom`] is that token transfers to other contracts may revert with the following custom error:
|
|
103
|
-
|
|
104
|
-
[source,text]
|
|
105
|
-
----
|
|
106
|
-
ERC1155InvalidReceiver("<ADDRESS>")
|
|
107
|
-
----
|
|
108
|
-
|
|
109
|
-
This is a good thing! It means that the recipient contract has not registered itself as aware of the ERC-1155 protocol, so transfers to it are disabled to *prevent tokens from being locked forever*. As an example, https://etherscan.io/token/0xa74476443119A942dE498590Fe1f2454d7D4aC0d?a=0xa74476443119A942dE498590Fe1f2454d7D4aC0d[the Golem contract currently holds over 350k `GNT` tokens], and lacks methods to get them out of there. This has happened to virtually every ERC20-backed project, usually due to user error.
|
|
110
|
-
|
|
111
|
-
In order for our contract to receive ERC-1155 tokens we can inherit from the convenience contract xref:api:token/ERC1155.adoc#ERC1155Holder[`ERC1155Holder`] which handles the registering for us. However, we need to remember to implement functionality to allow tokens to be transferred out of our contract:
|
|
112
|
-
|
|
113
|
-
[source,solidity]
|
|
114
|
-
----
|
|
115
|
-
include::api:example$token/ERC1155/MyERC115HolderContract.sol[]
|
|
116
|
-
----
|
|
117
|
-
|
|
118
|
-
We can also implement more complex scenarios using the xref:api:token/ERC1155.adoc#IERC1155Receiver-onERC1155Received-address-address-uint256-uint256-bytes-[`onERC1155Received`] and xref:api:token/ERC1155.adoc#IERC1155Receiver-onERC1155BatchReceived-address-address-uint256---uint256---bytes-[`onERC1155BatchReceived`] functions.
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
= Creating ERC-20 Supply
|
|
2
|
-
|
|
3
|
-
In this guide, you will learn how to create an ERC-20 token with a custom supply mechanism. We will showcase two idiomatic ways to use OpenZeppelin Contracts for this purpose that you will be able to apply to your smart contract development practice.
|
|
4
|
-
|
|
5
|
-
The standard interface implemented by tokens built on Ethereum is called ERC-20, and Contracts includes a widely used implementation of it: the aptly named xref:api:token/ERC20.adoc[`ERC20`] contract. This contract, like the standard itself, is quite simple and bare-bones. In fact, if you try to deploy an instance of `ERC20` as-is it will be quite literally useless... it will have no supply! What use is a token with no supply?
|
|
6
|
-
|
|
7
|
-
The way that supply is created is not defined in the ERC-20 document. Every token is free to experiment with its own mechanisms, ranging from the most decentralized to the most centralized, from the most naive to the most researched, and more.
|
|
8
|
-
|
|
9
|
-
[[fixed-supply]]
|
|
10
|
-
== Fixed Supply
|
|
11
|
-
|
|
12
|
-
Let's say we want a token with a fixed supply of 1000, initially allocated to the account that deploys the contract. If you've used Contracts v1, you may have written code like the following:
|
|
13
|
-
|
|
14
|
-
[source,solidity]
|
|
15
|
-
----
|
|
16
|
-
contract ERC20FixedSupply is ERC20 {
|
|
17
|
-
constructor() {
|
|
18
|
-
totalSupply += 1000;
|
|
19
|
-
balances[msg.sender] += 1000;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
----
|
|
23
|
-
|
|
24
|
-
Starting with Contracts v2, this pattern is not only discouraged, but disallowed. The variables `totalSupply` and `balances` are now private implementation details of `ERC20`, and you can't directly write to them. Instead, there is an internal xref:api:token/ERC20.adoc#ERC20-_mint-address-uint256-[`_mint`] function that will do exactly this:
|
|
25
|
-
|
|
26
|
-
[source,solidity]
|
|
27
|
-
----
|
|
28
|
-
contract ERC20FixedSupply is ERC20 {
|
|
29
|
-
constructor() ERC20("Fixed", "FIX") {
|
|
30
|
-
_mint(msg.sender, 1000);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
----
|
|
34
|
-
|
|
35
|
-
Encapsulating state like this makes it safer to extend contracts. For instance, in the first example we had to manually keep the `totalSupply` in sync with the modified balances, which is easy to forget. In fact, we omitted something else that is also easily forgotten: the `Transfer` event that is required by the standard, and which is relied on by some clients. The second example does not have this bug, because the internal `_mint` function takes care of it.
|
|
36
|
-
|
|
37
|
-
[[rewarding-miners]]
|
|
38
|
-
== Rewarding Miners
|
|
39
|
-
|
|
40
|
-
The internal xref:api:token/ERC20.adoc#ERC20-_mint-address-uint256-[`_mint`] function is the key building block that allows us to write ERC-20 extensions that implement a supply mechanism.
|
|
41
|
-
|
|
42
|
-
The mechanism we will implement is a token reward for the miners that produce Ethereum blocks. In Solidity, we can access the address of the current block's miner in the global variable `block.coinbase`. We will mint a token reward to this address whenever someone calls the function `mintMinerReward()` on our token. The mechanism may sound silly, but you never know what kind of dynamic this might result in, and it's worth analyzing and experimenting with!
|
|
43
|
-
|
|
44
|
-
[source,solidity]
|
|
45
|
-
----
|
|
46
|
-
contract ERC20WithMinerReward is ERC20 {
|
|
47
|
-
constructor() ERC20("Reward", "RWD") {}
|
|
48
|
-
|
|
49
|
-
function mintMinerReward() public {
|
|
50
|
-
_mint(block.coinbase, 1000);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
----
|
|
54
|
-
|
|
55
|
-
As we can see, `_mint` makes it super easy to do this correctly.
|
|
56
|
-
|
|
57
|
-
[[automating-the-reward]]
|
|
58
|
-
== Automating the Reward
|
|
59
|
-
|
|
60
|
-
So far our supply mechanism was triggered manually, but `ERC20` also allows us to extend the core functionality of the token through the xref:api:token/ERC20.adoc#ERC20-_update-address-address-uint256-[`_update`] function.
|
|
61
|
-
|
|
62
|
-
Adding to the supply mechanism from the previous section, we can use this function to mint a miner reward for every token transfer that is included in the blockchain.
|
|
63
|
-
|
|
64
|
-
```solidity
|
|
65
|
-
include::api:example$ERC20WithAutoMinerReward.sol[]
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
[[wrapping-up]]
|
|
69
|
-
== Wrapping Up
|
|
70
|
-
|
|
71
|
-
We've seen how to implement an ERC-20 supply mechanism: internally through `_mint`. Hopefully this has helped you understand how to use OpenZeppelin Contracts and some of the design principles behind it, and you can apply them to your own smart contracts.
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
= ERC-20
|
|
2
|
-
|
|
3
|
-
An ERC-20 token contract keeps track of xref:tokens.adoc#different-kinds-of-tokens[_fungible_ tokens]: any one token is exactly equal to any other token; no tokens have special rights or behavior associated with them. This makes ERC-20 tokens useful for things like a *medium of exchange currency*, *voting rights*, *staking*, and more.
|
|
4
|
-
|
|
5
|
-
OpenZeppelin Contracts provides many ERC20-related contracts. On the xref:api:token/ERC20.adoc[`API reference`] you'll find detailed information on their properties and usage.
|
|
6
|
-
|
|
7
|
-
[[constructing-an-erc20-token-contract]]
|
|
8
|
-
== Constructing an ERC-20 Token Contract
|
|
9
|
-
|
|
10
|
-
Using Contracts, we can easily create our own ERC-20 token contract, which will be used to track _Gold_ (GLD), an internal currency in a hypothetical game.
|
|
11
|
-
|
|
12
|
-
Here's what our GLD token might look like.
|
|
13
|
-
|
|
14
|
-
[source,solidity]
|
|
15
|
-
----
|
|
16
|
-
include::api:example$token/ERC20/GLDToken.sol[]
|
|
17
|
-
----
|
|
18
|
-
|
|
19
|
-
Our contracts are often used via https://solidity.readthedocs.io/en/latest/contracts.html#inheritance[inheritance], and here we're reusing xref:api:token/ERC20.adoc#erc20[`ERC20`] for both the basic standard implementation and the xref:api:token/ERC20.adoc#ERC20-name--[`name`], xref:api:token/ERC20.adoc#ERC20-symbol--[`symbol`], and xref:api:token/ERC20.adoc#ERC20-decimals--[`decimals`] optional extensions. Additionally, we're creating an `initialSupply` of tokens, which will be assigned to the address that deploys the contract.
|
|
20
|
-
|
|
21
|
-
TIP: For a more complete discussion of ERC-20 supply mechanisms, see xref:erc20-supply.adoc[Creating ERC-20 Supply].
|
|
22
|
-
|
|
23
|
-
That's it! Once deployed, we will be able to query the deployer's balance:
|
|
24
|
-
|
|
25
|
-
[source,javascript]
|
|
26
|
-
----
|
|
27
|
-
> GLDToken.balanceOf(deployerAddress)
|
|
28
|
-
1000000000000000000000
|
|
29
|
-
----
|
|
30
|
-
|
|
31
|
-
We can also xref:api:token/ERC20.adoc#IERC20-transfer-address-uint256-[transfer] these tokens to other accounts:
|
|
32
|
-
|
|
33
|
-
[source,javascript]
|
|
34
|
-
----
|
|
35
|
-
> GLDToken.transfer(otherAddress, 300000000000000000000)
|
|
36
|
-
> GLDToken.balanceOf(otherAddress)
|
|
37
|
-
300000000000000000000
|
|
38
|
-
> GLDToken.balanceOf(deployerAddress)
|
|
39
|
-
700000000000000000000
|
|
40
|
-
----
|
|
41
|
-
|
|
42
|
-
[[a-note-on-decimals]]
|
|
43
|
-
== A Note on `decimals`
|
|
44
|
-
|
|
45
|
-
Often, you'll want to be able to divide your tokens into arbitrary amounts: say, if you own `5 GLD`, you may want to send `1.5 GLD` to a friend, and keep `3.5 GLD` to yourself. Unfortunately, Solidity and the EVM do not support this behavior: only integer (whole) numbers can be used, which poses an issue. You may send `1` or `2` tokens, but not `1.5`.
|
|
46
|
-
|
|
47
|
-
To work around this, xref:api:token/ERC20.adoc#ERC20[`ERC20`] provides a xref:api:token/ERC20.adoc#ERC20-decimals--[`decimals`] field, which is used to specify how many decimal places a token has. To be able to transfer `1.5 GLD`, `decimals` must be at least `1`, since that number has a single decimal place.
|
|
48
|
-
|
|
49
|
-
How can this be achieved? It's actually very simple: a token contract can use larger integer values, so that a balance of `50` will represent `5 GLD`, a transfer of `15` will correspond to `1.5 GLD` being sent, and so on.
|
|
50
|
-
|
|
51
|
-
It is important to understand that `decimals` is _only used for display purposes_. All arithmetic inside the contract is still performed on integers, and it is the different user interfaces (wallets, exchanges, etc.) that must adjust the displayed values according to `decimals`. The total token supply and balance of each account are not specified in `GLD`: you need to divide by `10 ** decimals` to get the actual `GLD` amount.
|
|
52
|
-
|
|
53
|
-
You'll probably want to use a `decimals` value of `18`, just like Ether and most ERC-20 token contracts in use, unless you have a very special reason not to. When minting tokens or transferring them around, you will be actually sending the number `num GLD * (10 ** decimals)`.
|
|
54
|
-
|
|
55
|
-
NOTE: By default, `ERC20` uses a value of `18` for `decimals`. To use a different value, you will need to override the `decimals()` function in your contract.
|
|
56
|
-
|
|
57
|
-
```solidity
|
|
58
|
-
function decimals() public view virtual override returns (uint8) {
|
|
59
|
-
return 16;
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
So if you want to send `5` tokens using a token contract with 18 decimals, the method to call will actually be:
|
|
64
|
-
|
|
65
|
-
```solidity
|
|
66
|
-
transfer(recipient, 5 * (10 ** 18));
|
|
67
|
-
```
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
= ERC-4626
|
|
2
|
-
:stem: latexmath
|
|
3
|
-
|
|
4
|
-
https://eips.ethereum.org/EIPS/eip-4626[ERC-4626] is an extension of xref:erc20.adoc[ERC-20] that proposes a standard interface for token vaults. This standard interface can be used by widely different contracts (including lending markets, aggregators, and intrinsically interest bearing tokens), which brings a number of subtleties. Navigating these potential issues is essential to implementing a compliant and composable token vault.
|
|
5
|
-
|
|
6
|
-
We provide a base implementation of ERC-4626 that includes a simple vault. This contract is designed in a way that allows developers to easily re-configure the vault's behavior, with minimal overrides, while staying compliant. In this guide, we will discuss some security considerations that affect ERC-4626. We will also discuss common customizations of the vault.
|
|
7
|
-
|
|
8
|
-
[[inflation-attack]]
|
|
9
|
-
== Security concern: Inflation attack
|
|
10
|
-
|
|
11
|
-
=== Visualizing the vault
|
|
12
|
-
|
|
13
|
-
In exchange for the assets deposited into an ERC-4626 vault, a user receives shares. These shares can later be burned to redeem the corresponding underlying assets. The number of shares a user gets depends on the amount of assets they put in and on the exchange rate of the vault. This exchange rate is defined by the current liquidity held by the vault.
|
|
14
|
-
|
|
15
|
-
- If a vault has 100 tokens to back 200 shares, then each share is worth 0.5 assets.
|
|
16
|
-
- If a vault has 200 tokens to back 100 shares, then each share is worth 2.0 assets.
|
|
17
|
-
|
|
18
|
-
In other words, the exchange rate can be defined as the slope of the line that passes through the origin and the current number of assets and shares in the vault. Deposits and withdrawals move the vault in this line.
|
|
19
|
-
|
|
20
|
-
image::erc4626-rate-linear.png[Exchange rates in linear scale]
|
|
21
|
-
|
|
22
|
-
When plotted in log-log scale, the rate is defined similarly, but appears differently (because the point (0,0) is infinitely far away). Rates are represented by "diagonal" lines with different offsets.
|
|
23
|
-
|
|
24
|
-
image::erc4626-rate-loglog.png[Exchange rates in logarithmic scale]
|
|
25
|
-
|
|
26
|
-
In such a representation, widely different rates can be clearly visible in the same graph. This wouldn't be the case in linear scale.
|
|
27
|
-
|
|
28
|
-
image::erc4626-rate-loglogext.png[More exchange rates in logarithmic scale]
|
|
29
|
-
|
|
30
|
-
=== The attack
|
|
31
|
-
|
|
32
|
-
When depositing tokens, the number of shares a user gets is rounded towards zero. This rounding takes away value from the user in favor of the vault (i.e. in favor of all the current shareholders). This rounding is often negligible because of the amount at stake. If you deposit 1e9 shares worth of tokens, the rounding will have you lose at most 0.0000001% of your deposit. However if you deposit 10 shares worth of tokens, you could lose 10% of your deposit. Even worse, if you deposit <1 share worth of tokens, then you get 0 shares, and you basically made a donation.
|
|
33
|
-
|
|
34
|
-
For a given amount of assets, the more shares you receive the safer you are. If you want to limit your losses to at most 1%, you need to receive at least 100 shares.
|
|
35
|
-
|
|
36
|
-
image::erc4626-deposit.png[Depositing assets]
|
|
37
|
-
|
|
38
|
-
In the figure we can see that for a given deposit of 500 assets, the number of shares we get and the corresponding rounding losses depend on the exchange rate. If the exchange rate is that of the orange curve, we are getting less than a share, so we lose 100% of our deposit. However, if the exchange rate is that of the green curve, we get 5000 shares, which limits our rounding losses to at most 0.02%.
|
|
39
|
-
|
|
40
|
-
image::erc4626-mint.png[Minting shares]
|
|
41
|
-
|
|
42
|
-
Symmetrically, if we focus on limiting our losses to a maximum of 0.5%, we need to get at least 200 shares. With the green exchange rate that requires just 20 tokens, but with the orange rate that requires 200000 tokens.
|
|
43
|
-
|
|
44
|
-
We can clearly see that the blue and green curves correspond to vaults that are safer than the yellow and orange curves.
|
|
45
|
-
|
|
46
|
-
The idea of an inflation attack is that an attacker can donate assets to the vault to move the rate curve to the right, and make the vault unsafe.
|
|
47
|
-
|
|
48
|
-
image::erc4626-attack.png[Inflation attack without protection]
|
|
49
|
-
|
|
50
|
-
Figure 6 shows how an attacker can manipulate the rate of an empty vault. First the attacker must deposit a small amount of tokens (1 token) and follow up with a donation of 1e5 tokens directly to the vault to move the exchange rate "right". This puts the vault in a state where any deposit smaller than 1e5 would be completely lost to the vault. Given that the attacker is the only shareholder (from their donation), the attacker would steal all the tokens deposited.
|
|
51
|
-
|
|
52
|
-
An attacker would typically wait for a user to do the first deposit into the vault, and would frontrun that operation with the attack described above. The risk is low, and the size of the "donation" required to manipulate the vault is equivalent to the size of the deposit that is being attacked.
|
|
53
|
-
|
|
54
|
-
In math that gives:
|
|
55
|
-
|
|
56
|
-
- stem:[a_0] the attacker deposit
|
|
57
|
-
- stem:[a_1] the attacker donation
|
|
58
|
-
- stem:[u] the user deposit
|
|
59
|
-
|
|
60
|
-
[%header,cols=4*]
|
|
61
|
-
|===
|
|
62
|
-
|
|
|
63
|
-
| Assets
|
|
64
|
-
| Shares
|
|
65
|
-
| Rate
|
|
66
|
-
|
|
67
|
-
| initial
|
|
68
|
-
| stem:[0]
|
|
69
|
-
| stem:[0]
|
|
70
|
-
| -
|
|
71
|
-
|
|
72
|
-
| after attacker's deposit
|
|
73
|
-
| stem:[a_0]
|
|
74
|
-
| stem:[a_0]
|
|
75
|
-
| stem:[1]
|
|
76
|
-
|
|
77
|
-
| after attacker's donation
|
|
78
|
-
| stem:[a_0+a_1]
|
|
79
|
-
| stem:[a_0]
|
|
80
|
-
| stem:[\frac{a_0}{a_0+a_1}]
|
|
81
|
-
|===
|
|
82
|
-
|
|
83
|
-
This means a deposit of stem:[u] will give stem:[\frac{u \times a_0}{a_0 + a_1}] shares.
|
|
84
|
-
|
|
85
|
-
For the attacker to dilute that deposit to 0 shares, causing the user to lose all its deposit, it must ensure that
|
|
86
|
-
|
|
87
|
-
[stem]
|
|
88
|
-
++++
|
|
89
|
-
\frac{u \times a_0}{a_0+a_1} < 1 \iff u < 1 + \frac{a_1}{a_0}
|
|
90
|
-
++++
|
|
91
|
-
|
|
92
|
-
Using stem:[a_0 = 1] and stem:[a_1 = u] is enough. So the attacker only needs stem:[u+1] assets to perform a successful attack.
|
|
93
|
-
|
|
94
|
-
It is easy to generalize the above results to scenarios where the attacker is going after a smaller fraction of the user's deposit. In order to target stem:[\frac{u}{n}], the user needs to suffer rounding of a similar fraction, which means the user must receive at most stem:[n] shares. This results in:
|
|
95
|
-
|
|
96
|
-
[stem]
|
|
97
|
-
++++
|
|
98
|
-
\frac{u \times a_0}{a_0+a_1} < n \iff \frac{u}{n} < 1 + \frac{a_1}{a_0}
|
|
99
|
-
++++
|
|
100
|
-
|
|
101
|
-
In this scenario, the attack is stem:[n] times less powerful (in how much it is stealing) and costs stem:[n] times less to execute. In both cases, the amount of funds the attacker needs to commit is equivalent to its potential earnings.
|
|
102
|
-
|
|
103
|
-
=== Defending with a virtual offset
|
|
104
|
-
|
|
105
|
-
The defense we propose is based on the approach used in link:https://github.com/boringcrypto/YieldBox[YieldBox]. It consists of two parts:
|
|
106
|
-
|
|
107
|
-
- Use an offset between the "precision" of the representation of shares and assets. Said otherwise, we use more decimal places to represent the shares than the underlying token does to represent the assets.
|
|
108
|
-
- Include virtual shares and virtual assets in the exchange rate computation. These virtual assets enforce the conversion rate when the vault is empty.
|
|
109
|
-
|
|
110
|
-
These two parts work together in enforcing the security of the vault. First, the increased precision corresponds to a high rate, which we saw is safer as it reduces the rounding error when computing the amount of shares. Second, the virtual assets and shares (in addition to simplifying a lot of the computations) capture part of the donation, making it unprofitable for a developer to perform an attack.
|
|
111
|
-
|
|
112
|
-
Following the previous math definitions, we have:
|
|
113
|
-
|
|
114
|
-
- stem:[\delta] the vault offset
|
|
115
|
-
- stem:[a_0] the attacker deposit
|
|
116
|
-
- stem:[a_1] the attacker donation
|
|
117
|
-
- stem:[u] the user deposit
|
|
118
|
-
|
|
119
|
-
[%header,cols=4*]
|
|
120
|
-
|===
|
|
121
|
-
|
|
|
122
|
-
| Assets
|
|
123
|
-
| Shares
|
|
124
|
-
| Rate
|
|
125
|
-
|
|
126
|
-
| initial
|
|
127
|
-
| stem:[1]
|
|
128
|
-
| stem:[10^\delta]
|
|
129
|
-
| stem:[10^\delta]
|
|
130
|
-
|
|
131
|
-
| after attacker's deposit
|
|
132
|
-
| stem:[1+a_0]
|
|
133
|
-
| stem:[10^\delta \times (1+a_0)]
|
|
134
|
-
| stem:[10^\delta]
|
|
135
|
-
|
|
136
|
-
| after attacker's donation
|
|
137
|
-
| stem:[1+a_0+a_1]
|
|
138
|
-
| stem:[10^\delta \times (1+a_0)]
|
|
139
|
-
| stem:[10^\delta \times \frac{1+a_0}{1+a_0+a_1}]
|
|
140
|
-
|===
|
|
141
|
-
|
|
142
|
-
One important thing to note is that the attacker only owns a fraction stem:[\frac{a_0}{1 + a_0}] of the shares, so when doing the donation, he will only be able to recover that fraction stem:[\frac{a_1 \times a_0}{1 + a_0}] of the donation. The remaining stem:[\frac{a_1}{1+a_0}] are captured by the vault.
|
|
143
|
-
|
|
144
|
-
[stem]
|
|
145
|
-
++++
|
|
146
|
-
\mathit{loss} = \frac{a_1}{1+a_0}
|
|
147
|
-
++++
|
|
148
|
-
|
|
149
|
-
When the user deposits stem:[u], he receives
|
|
150
|
-
|
|
151
|
-
[stem]
|
|
152
|
-
++++
|
|
153
|
-
10^\delta \times u \times \frac{1+a_0}{1+a_0+a_1}
|
|
154
|
-
++++
|
|
155
|
-
|
|
156
|
-
For the attacker to dilute that deposit to 0 shares, causing the user to lose all its deposit, it must ensure that
|
|
157
|
-
|
|
158
|
-
[stem]
|
|
159
|
-
++++
|
|
160
|
-
10^\delta \times u \times \frac{1+a_0}{1+a_0+a_1} < 1
|
|
161
|
-
++++
|
|
162
|
-
|
|
163
|
-
[stem]
|
|
164
|
-
++++
|
|
165
|
-
\iff 10^\delta \times u < \frac{1+a_0+a_1}{1+a_0}
|
|
166
|
-
++++
|
|
167
|
-
|
|
168
|
-
[stem]
|
|
169
|
-
++++
|
|
170
|
-
\iff 10^\delta \times u < 1 + \frac{a_1}{1+a_0}
|
|
171
|
-
++++
|
|
172
|
-
|
|
173
|
-
[stem]
|
|
174
|
-
++++
|
|
175
|
-
\iff 10^\delta \times u \le \mathit{loss}
|
|
176
|
-
++++
|
|
177
|
-
|
|
178
|
-
- If the offset is 0, the attacker loss is at least equal to the user's deposit.
|
|
179
|
-
- If the offset is greater than 0, the attacker will have to suffer losses that are orders of magnitude bigger than the amount of value that can hypothetically be stolen from the user.
|
|
180
|
-
|
|
181
|
-
This shows that even with an offset of 0, the virtual shares and assets make this attack non profitable for the attacker. Bigger offsets increase the security even further by making any attack on the user extremely wasteful.
|
|
182
|
-
|
|
183
|
-
The following figure shows how the offset impacts the initial rate and limits the ability of an attacker with limited funds to inflate it effectively.
|
|
184
|
-
|
|
185
|
-
image::erc4626-attack-3a.png[Inflation attack without offset=3]
|
|
186
|
-
stem:[\delta = 3], stem:[a_0 = 1], stem:[a_1 = 10^5]
|
|
187
|
-
|
|
188
|
-
image::erc4626-attack-3b.png[Inflation attack without offset=3 and an attacker deposit that limits its losses]
|
|
189
|
-
stem:[\delta = 3], stem:[a_0 = 100], stem:[a_1 = 10^5]
|
|
190
|
-
|
|
191
|
-
image::erc4626-attack-6.png[Inflation attack without offset=6]
|
|
192
|
-
stem:[\delta = 6], stem:[a_0 = 1], stem:[a_1 = 10^5]
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
[[fees]]
|
|
196
|
-
== Custom behavior: Adding fees to the vault
|
|
197
|
-
|
|
198
|
-
In an ERC-4626 vaults, fees can be captured during the deposit/mint and/or during the withdraw/redeem steps. In both cases it is essential to remain compliant with the ERC-4626 requirements with regard to the preview functions.
|
|
199
|
-
|
|
200
|
-
For example, if calling `deposit(100, receiver)`, the caller should deposit exactly 100 underlying tokens, including fees, and the receiver should receive a number of shares that matches the value returned by `previewDeposit(100)`. Similarly, `previewMint` should account for the fees that the user will have to pay on top of share's cost.
|
|
201
|
-
|
|
202
|
-
As for the `Deposit` event, while this is less clear in the EIP spec itself, there seems to be consensus that it should include the number of assets paid for by the user, including the fees.
|
|
203
|
-
|
|
204
|
-
On the other hand, when withdrawing assets, the number given by the user should correspond to what he receives. Any fees should be added to the quote (in shares) performed by `previewWithdraw`.
|
|
205
|
-
|
|
206
|
-
The `Withdraw` event should include the number of shares the user burns (including fees) and the number of assets the user actually receives (after fees are deducted).
|
|
207
|
-
|
|
208
|
-
The consequence of this design is that both the `Deposit` and `Withdraw` events will describe two exchange rates. The spread between the "Buy-in" and the "Exit" prices correspond to the fees taken by the vault.
|
|
209
|
-
|
|
210
|
-
The following example describes how fees proportional to the deposited/withdrawn amount can be implemented:
|
|
211
|
-
|
|
212
|
-
```solidity
|
|
213
|
-
include::api:example$ERC4626Fees.sol[]
|
|
214
|
-
```
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
= ERC-6909
|
|
2
|
-
|
|
3
|
-
ERC-6909 is a draft EIP that draws on ERC-1155 learnings since it was published in 2018. The main goals of ERC-6909 is to decrease gas costs and complexity--this is mainly accomplished by removing batching and callbacks.
|
|
4
|
-
|
|
5
|
-
TIP: To understand the inspiration for a multi token standard, see the xref:erc1155.adoc#multi-token-standard[multi token standard] section within the EIP-1155 docs.
|
|
6
|
-
|
|
7
|
-
== Changes from ERC-1155
|
|
8
|
-
|
|
9
|
-
There are three main changes from ERC-1155 which are as follows:
|
|
10
|
-
|
|
11
|
-
. The removal of batch operations.
|
|
12
|
-
. The removal of transfer callbacks.
|
|
13
|
-
. Granularization in approvals--approvals can be set globally (as operators) or as amounts per token (inspired by ERC20).
|
|
14
|
-
|
|
15
|
-
== Constructing an ERC-6909 Token Contract
|
|
16
|
-
|
|
17
|
-
We'll use ERC-6909 to track multiple items in a game, each having their own unique attributes. All item types will by minted to the deployer of the contract, which we can later transfer to players. We'll also use the xref:api:token/ERC6909.adoc#ERC6909Metadata[`ERC6909Metadata`] extension to add decimals to our fungible items (the vanilla ERC-6909 implementation does not have decimals).
|
|
18
|
-
|
|
19
|
-
For simplicity, we will mint all items in the constructor--however, minting functionality could be added to the contract to mint on demand to players.
|
|
20
|
-
|
|
21
|
-
TIP: For an overview of minting mechanisms, check out xref:erc20-supply.adoc[Creating ERC-20 Supply].
|
|
22
|
-
|
|
23
|
-
Here's what a contract for tokenized items might look like:
|
|
24
|
-
|
|
25
|
-
[source,solidity]
|
|
26
|
-
----
|
|
27
|
-
include::api:example$token/ERC6909/ERC6909GameItems.sol[]
|
|
28
|
-
----
|
|
29
|
-
|
|
30
|
-
Note that there is no content URI functionality in the base implementation, but the xref:api:token/ERC6909.adoc#ERC6909ContentURI[`ERC6909ContentURI`] extension adds it. Additionally, the base implementation does not track total supplies, but the xref:api:token/ERC6909.adoc#ERC6909TokenSupply[`ERC6909TokenSupply`] extension tracks the total supply of each token id.
|
|
31
|
-
|
|
32
|
-
Once the contract is deployed, we will be able to query the deployer’s balance:
|
|
33
|
-
[source,javascript]
|
|
34
|
-
----
|
|
35
|
-
> gameItems.balanceOf(deployerAddress, 3)
|
|
36
|
-
1000000000
|
|
37
|
-
----
|
|
38
|
-
|
|
39
|
-
We can transfer items to player accounts:
|
|
40
|
-
[source,javascript]
|
|
41
|
-
----
|
|
42
|
-
> gameItems.transfer(playerAddress, 2, 1)
|
|
43
|
-
> gameItems.balanceOf(playerAddress, 2)
|
|
44
|
-
1
|
|
45
|
-
> gameItems.balanceOf(deployerAddress, 2)
|
|
46
|
-
0
|
|
47
|
-
----
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
= ERC-721
|
|
2
|
-
|
|
3
|
-
We've discussed how you can make a _fungible_ token using xref:erc20.adoc[ERC-20], but what if not all tokens are alike? This comes up in situations like *real estate*, *voting rights*, or *collectibles*, where some items are valued more than others, due to their usefulness, rarity, etc. ERC-721 is a standard for representing ownership of xref:tokens.adoc#different-kinds-of-tokens[_non-fungible_ tokens], that is, where each token is unique.
|
|
4
|
-
|
|
5
|
-
ERC-721 is a more complex standard than ERC-20, with multiple optional extensions, and is split across a number of contracts. The OpenZeppelin Contracts provide flexibility regarding how these are combined, along with custom useful extensions. Check out the xref:api:token/ERC721.adoc[API Reference] to learn more about these.
|
|
6
|
-
|
|
7
|
-
== Constructing an ERC-721 Token Contract
|
|
8
|
-
|
|
9
|
-
We'll use ERC-721 to track items in our game, which will each have their own unique attributes. Whenever one is to be awarded to a player, it will be minted and sent to them. Players are free to keep their token or trade it with other people as they see fit, as they would any other asset on the blockchain! Please note any account can call `awardItem` to mint items. To restrict what accounts can mint items we can add xref:access-control.adoc[Access Control].
|
|
10
|
-
|
|
11
|
-
Here's what a contract for tokenized items might look like:
|
|
12
|
-
|
|
13
|
-
[source,solidity]
|
|
14
|
-
----
|
|
15
|
-
include::api:example$token/ERC721/GameItem.sol[]
|
|
16
|
-
----
|
|
17
|
-
|
|
18
|
-
The xref:api:token/ERC721.adoc#ERC721URIStorage[`ERC721URIStorage`] contract is an implementation of ERC-721 that includes the metadata standard extensions (xref:api:token/ERC721.adoc#IERC721Metadata[`IERC721Metadata`]) as well as a mechanism for per-token metadata. That's where the xref:api:token/ERC721.adoc#ERC721-_setTokenURI-uint256-string-[`_setTokenURI`] method comes from: we use it to store an item's metadata.
|
|
19
|
-
|
|
20
|
-
Also note that, unlike ERC-20, ERC-721 lacks a `decimals` field, since each token is distinct and cannot be partitioned.
|
|
21
|
-
|
|
22
|
-
New items can be created:
|
|
23
|
-
|
|
24
|
-
[source,javascript]
|
|
25
|
-
----
|
|
26
|
-
> gameItem.awardItem(playerAddress, "https://game.example/item-id-8u5h2m.json")
|
|
27
|
-
Transaction successful. Transaction hash: 0x...
|
|
28
|
-
Events emitted:
|
|
29
|
-
- Transfer(0x0000000000000000000000000000000000000000, playerAddress, 7)
|
|
30
|
-
----
|
|
31
|
-
|
|
32
|
-
And the owner and metadata of each item queried:
|
|
33
|
-
|
|
34
|
-
[source,javascript]
|
|
35
|
-
----
|
|
36
|
-
> gameItem.ownerOf(7)
|
|
37
|
-
playerAddress
|
|
38
|
-
> gameItem.tokenURI(7)
|
|
39
|
-
"https://game.example/item-id-8u5h2m.json"
|
|
40
|
-
----
|
|
41
|
-
|
|
42
|
-
This `tokenURI` should resolve to a JSON document that might look something like:
|
|
43
|
-
|
|
44
|
-
[source,json]
|
|
45
|
-
----
|
|
46
|
-
{
|
|
47
|
-
"name": "Thor's hammer",
|
|
48
|
-
"description": "Mjölnir, the legendary hammer of the Norse god of thunder.",
|
|
49
|
-
"image": "https://game.example/item-id-8u5h2m.png",
|
|
50
|
-
"strength": 20
|
|
51
|
-
}
|
|
52
|
-
----
|
|
53
|
-
|
|
54
|
-
For more information about the `tokenURI` metadata JSON Schema, check out the https://eips.ethereum.org/EIPS/eip-721[ERC-721 specification].
|
|
55
|
-
|
|
56
|
-
NOTE: You'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game!
|
|
57
|
-
|
|
58
|
-
TIP: If you'd like to put all item information on-chain, you can extend ERC-721 to do so (though it will be rather costly) by providing a xref:utilities.adoc#base64[`Base64`] Data URI with the JSON schema encoded. You could also leverage IPFS to store the tokenURI information, but these techniques are out of the scope of this overview guide.
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
= Extending Contracts
|
|
2
|
-
|
|
3
|
-
Most of the OpenZeppelin Contracts are expected to be used via https://solidity.readthedocs.io/en/latest/contracts.html#inheritance[inheritance]: you will _inherit_ from them when writing your own contracts.
|
|
4
|
-
|
|
5
|
-
This is the commonly found `is` syntax, like in `contract MyToken is ERC20`.
|
|
6
|
-
|
|
7
|
-
[NOTE]
|
|
8
|
-
====
|
|
9
|
-
Unlike ``contract``s, Solidity ``library``s are not inherited from and instead rely on the https://solidity.readthedocs.io/en/latest/contracts.html#using-for[`using for`] syntax.
|
|
10
|
-
|
|
11
|
-
OpenZeppelin Contracts has some ``library``s: most are in the xref:api:utils.adoc[Utils] directory.
|
|
12
|
-
====
|
|
13
|
-
|
|
14
|
-
== Overriding
|
|
15
|
-
|
|
16
|
-
Inheritance is often used to add the parent contract's functionality to your own contract, but that's not all it can do. You can also _change_ how some parts of the parent behave using _overrides_.
|
|
17
|
-
|
|
18
|
-
For example, imagine you want to change xref:api:access.adoc#AccessControl[`AccessControl`] so that xref:api:access.adoc#AccessControl-revokeRole-bytes32-address-[`revokeRole`] can no longer be called. This can be achieved using overrides:
|
|
19
|
-
|
|
20
|
-
```solidity
|
|
21
|
-
include::api:example$access-control/AccessControlModified.sol[]
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
The old `revokeRole` is then replaced by our override, and any calls to it will immediately revert. We cannot _remove_ the function from the contract, but reverting on all calls is good enough.
|
|
25
|
-
|
|
26
|
-
=== Calling `super`
|
|
27
|
-
|
|
28
|
-
Sometimes you want to _extend_ a parent's behavior, instead of outright changing it to something else. This is where `super` comes in.
|
|
29
|
-
|
|
30
|
-
The `super` keyword will let you call functions defined in a parent contract, even if they are overridden. This mechanism can be used to add additional checks to a function, emit events, or otherwise add functionality as you see fit.
|
|
31
|
-
|
|
32
|
-
TIP: For more information on how overrides work, head over to the https://solidity.readthedocs.io/en/latest/contracts.html#index-17[official Solidity documentation].
|
|
33
|
-
|
|
34
|
-
Here is a modified version of xref:api:access.adoc#AccessControl[`AccessControl`] where xref:api:access.adoc#AccessControl-revokeRole-bytes32-address-[`revokeRole`] cannot be used to revoke the `DEFAULT_ADMIN_ROLE`:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
```solidity
|
|
38
|
-
include::api:example$access-control/AccessControlNonRevokableAdmin.sol[]
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
The `super.revokeRole` statement at the end will invoke ``AccessControl``'s original version of `revokeRole`, the same code that would've run if there were no overrides in place.
|
|
42
|
-
|
|
43
|
-
NOTE: The same rule is implemented and extended in xref:api:access.adoc#AccessControlDefaultAdminRules[`AccessControlDefaultAdminRules`], an extension that also adds enforced security measures for the `DEFAULT_ADMIN_ROLE`.
|
|
44
|
-
|
|
45
|
-
== Security
|
|
46
|
-
|
|
47
|
-
The maintainers of OpenZeppelin Contracts are mainly concerned with the correctness and security of the code as published in the library, and the combinations of base contracts with the official extensions from the library.
|
|
48
|
-
|
|
49
|
-
Custom overrides, especially to hooks, can disrupt important assumptions and may introduce security risks in the code that was previously secure. While we try to ensure the contracts remain secure in the face of a wide range of potential customizations, this is done in a best-effort manner. While we try to document all important assumptions, this should not be relied upon. Custom overrides should be carefully reviewed and checked against the source code of the contract they are customizing to fully understand their impact and guarantee their security.
|
|
50
|
-
|
|
51
|
-
The way functions interact internally should not be assumed to stay stable across releases of the library. For example, a function that is used in one context in a particular release may not be used in the same context in the next release. Contracts that override functions should revalidate their assumptions when updating the version of OpenZeppelin Contracts they are built on.
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
= Frequently Asked Questions
|
|
2
|
-
|
|
3
|
-
== Can I restrict a function to EOAs only?
|
|
4
|
-
|
|
5
|
-
When calling external addresses from your contract it is unsafe to assume that an address is an externally-owned account (EOA) and not a contract. Attempting to prevent calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract constructor.
|
|
6
|
-
|
|
7
|
-
Although checking that the address has code, `address.code.length > 0`, may seem to differentiate contracts from EOAs, it can only say that an address is currently a contract, and its negation (that an address is not currently a contract) does not imply that the address is an EOA. Some counterexamples are:
|
|
8
|
-
|
|
9
|
-
- address of a contract in construction
|
|
10
|
-
- address where a contract will be created
|
|
11
|
-
- address where a contract lived, but was destroyed
|
|
12
|
-
|
|
13
|
-
Furthermore, an address will be considered a contract within the same transaction where it is scheduled for destruction by `SELFDESTRUCT`, which only has an effect at the end of the entire transaction.
|