1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- = Utilities
- OpenZeppelin provides a ton of useful utilities that you can use in your project. Here are some of the more popular ones:
- [[cryptography]]
- == Cryptography
- * link:api/cryptography#ecdsa[`ECDSA`] — provides functions for recovering and managing Ethereum account ECDSA signatures:
- * to use it, declare: `using ECDSA for bytes32;`
- * signatures are tightly packed, 65 byte `bytes` that look like `{v (1)} {r (32)} {s (32)}`
- ** this is the default from `web3.eth.sign` so you probably don't need to worry about this format
- * recover the signer using link:api/cryptography#ECDSA.recover(bytes32,bytes)[`myDataHash.recover(signature)`]
- * if you are using `eth_personalSign`, the signer will hash your data and then add the prefix `\x19Ethereum Signed Message:\n`, so if you're attempting to recover the signer of an Ethereum signed message hash, you'll want to use link:api/cryptography#ECDSA.toEthSignedMessageHash(bytes32)[`toEthSignedMessageHash`]
- Use these functions in combination to verify that a user has signed some information on-chain:
- [source,solidity]
- ----
- keccack256(
- abi.encodePacked(
- someData,
- moreData
- )
- )
- .toEthSignedMessageHash()
- .recover(signature)
- ----
- * link:api/cryptography#merkleproof[`MerkleProof`] — provides link:api/cryptography#MerkleProof.verify(bytes32%5B%5D,bytes32,bytes32)[`verify`] for verifying merkle proofs.
- [[introspection]]
- == Introspection
- In Solidity, it's frequently helpful to know whether or not a contract supports an interface you'd like to use. ERC165 is a standard that helps do runtime interface detection. OpenZeppelin provides some helpers, both for implementing ERC165 in your contracts and querying other contracts:
- * link:api/introspection#ierc165[`IERC165`] — this is the ERC165 interface that defines link:api/introspection#IERC165.supportsInterface(bytes4)[`supportsInterface`]. When implementing ERC165, you'll conform to this interface.
- * link:api/introspection#erc165[`ERC165`] — inherit this contract if you'd like to support interface detection using a lookup table in contract storage. You can register interfaces using link:api/introspection#ERC165._registerInterface(bytes4)[`_registerInterface(bytes4)`]: check out example usage as part of the ERC721 implementation.
- * link:api/introspection#erc165checker[`ERC165Checker`] — ERC165Checker simplifies the process of checking whether or not a contract supports an interface you care about.
- * include with `using ERC165Checker for address;`
- * link:api/introspection#ERC165Checker._supportsInterface(address,bytes4)[`myAddress._supportsInterface(bytes4)`]
- * link:api/introspection#ERC165Checker._supportsAllInterfaces(address,bytes4%5B%5D)[`myAddress._supportsAllInterfaces(bytes4[])`]
- [source,solidity]
- ----
- contract MyContract {
- using ERC165Checker for address;
- bytes4 private InterfaceId_ERC721 = 0x80ac58cd;
- /**
- * @dev transfer an ERC721 token from this contract to someone else
- */
- function transferERC721(
- address token,
- address to,
- uint256 tokenId
- )
- public
- {
- require(token.supportsInterface(InterfaceId_ERC721), "IS_NOT_721_TOKEN");
- IERC721(token).transferFrom(address(this), to, tokenId);
- }
- }
- ----
- [[math]]
- == Math
- The most popular math related library OpenZeppelin provides is link:api/math#safemath[`SafeMath`], which provides mathematical functions that protect your contract from overflows and underflows.
- Include the contract with `using SafeMath for uint256;` and then call the functions:
- * `myNumber.add(otherNumber)`
- * `myNumber.sub(otherNumber)`
- * `myNumber.div(otherNumber)`
- * `myNumber.mul(otherNumber)`
- * `myNumber.mod(otherNumber)`
- Easy!
- [[payment]]
- == Payment
- Want to split some payments between multiple people? Maybe you have an app that sends 30% of art purchases to the original creator and 70% of the profits to the current owner; you can build that with link:api/payment#paymentsplitter[`PaymentSplitter`]!
- In solidity, there are some security concerns with blindly sending money to accounts, since it allows them to execute arbitrary code. You can read up on these security concerns in the https://consensys.github.io/smart-contract-best-practices/[Ethereum Smart Contract Best Practices] website. One of the ways to fix reentrancy and stalling problems is, instead of immediately sending Ether to accounts that need it, you can use link:api/payment#pullpayment[`PullPayment`], which offers an link:api/payment#PullPayment._asyncTransfer(address,uint256)[`_asyncTransfer`] function for sending money to something and requesting that they link:api/payment#PullPayment.withdrawPayments(address%20payable)[`withdrawPayments()`] it later.
- If you want to Escrow some funds, check out link:api/payment#escrow[`Escrow`] and link:api/payment#conditionalescrow[`ConditionalEscrow`] for governing the release of some escrowed Ether.
- [[misc]]
- === Misc
- Want to check if an address is a contract? Use link:api/utils#address[`Address`] and link:api/utils#Address.isContract(address)[`Address.isContract()`].
- Want to keep track of some numbers that increment by 1 every time you want another one? Check out link:api/drafts#counter[`Counter`]. This is especially useful for creating incremental ERC721 `tokenId`s like we did in the last section.
|