Solidity contracts development library which uses HardHat consisting of upgradeable contracts, Hardhat plugins and configurations, tooling and testing utilities.
Date | Scope | Commit | Package version | Auditor | Report |
---|---|---|---|---|---|
26/09/2022 | Full library | 05666c7112a5637b9ec13b6883cb626982062244 | 0.2.0 | Solidified | link |
14/11/2022 | metatx/*, token/ERC20/* | 4b4cf4535be8367ef67b2827b32ea48a2d70e79c | 0.3.0 | Halborn | link |
28/06/2023 | token/ERC20/preset/*, payment/CumulativeMerkleClaim.sol | c813045b79473a100e8005c7f1ce6ae340f7d235 | 2.0.0 | Solidified | link |
18/10/2023 | token/ERC721/preset/*, token/ERC721/**/ERC721Metadata*.so;l, token/ERC1155/preset/*, token/ERC1155/**/ERC1155Metadata*.sol, token/metadata/* | fa9ca10004562eed33e9ac1ed316a2d8342b1c02 | 3.0.0 | Solidified | link |
The contracts are designed to be usable in any setup, behind a proxy or not. To achieve this, every storage is managed via diamond storage pattern.
The solidity files are structured as follow:
libraries/XYZStorage.sol
: Library managing the diamond storage and the core contract logic.
Does not deal with access control and sender-related logic (such as for meta-transactions).base/XYZBase.sol
: Base abstract proxiable contract. Should be inherited by a proxied contract implementation.
Deals with access control and sender-related logic. Does not deal with initialization sequence.facets/XYZFacet.sol
: Deployable diamond facet. Should be deployed and used via a diamond proxy.
Deals with access control and sender-related logic. Provides the initialization sequence via an initialization function.XYZ.sol
: Abstract immutable contract. Should be inherited by an immutable contract implementation.
Deals with access control and sender-related logic. Provides the initialization sequence via itsconstructor
.
To use a contract, simply import it in your code, for example:
import "@animoca/ethereum-contracts/contracts/access/ContractOwnership.sol";
contract MyContract is ContractOwnership {
// my code...
}
The compiled artifacts are available in the artifacts
folder.
All the contracts in this library support ERC2771-style meta-transactions.
Meta-transactions can be enabled through the use of the ForwarderRegistry
. The ForwarderRegistry
allows users to define which ERC2771 meta-transaction forwarders are authorized to be used for their specific wallet. Enabling the registry mechanism in a contract can be achieved by inheriting ForwarderRegistryContext
(for a stand-alone contract) or ForwarderRegistryContextBase
(for a diamond facet). All the deployable contracts in this library are ForwarderRegistryContext
-enabled.
As a user, There are two ways to approve/revoke a meta-transaction forwarder:
- Direct way: the wallet directly calls
approveForwarder(address forwarder, bool approved)
. - Forwarded way: the wallet signs an EIP712
ApproveForwarder(address forwarder,bool approved,uint256 nonce)
message for the forwarder, then the forwarder callsapproveForwarder(bool approved, bytes signature, SignatureType signatureType)
. - Approve and Forward way: see below.
Forwarding an EIP-2771 meta-transaction can be done in a few different ways:
- Direct forwarding: after the forwarder has been approved, it can directly call the target contract.
ForwarderRegistry
forwarding: TheForwarderRegistry
can also be used to forward the meta-transactions:- after a forwarder has been approved, it can call
forward(address target, bytes data)
on theForwarderRegistry
. - without being approved, but with an EIP712
ApproveForwarder(address forwarder,bool approved,uint256 nonce)
message signed by the user, a forwarder can callapproveAndForward(bytes signature, SignatureType signatureType, address target, bytes data)
on theForwarderRegistry
. This will approve the forwarder and then forward the meta-transaction to the target contract. This method is a shortcut enabling meta-transactions usage from the first user transaction.
- after a forwarder has been approved, it can call
The compilation artifacts, including the debug information, are available in the artifacts
folder, both in the git repository and the release packages. These artifacts can be imported in dependents projects and used in tests or migration scripts with the following hardhat configuration:
external: {
contracts: [
{
artifacts: 'node_modules/@animoca/ethereum-contracts/artifacts',
},
],
},
Some behaviors, such as some token standards extensively test the whole standard logic. For example, you can test the correct implementation of your ERC20 token contract with the function behavesLikeERC20
.
To install the module in your project, add it as an npm dependency:
yarn add -D @animoca/ethereum-contracts hardhat
or
npm add --save-dev @animoca/ethereum-contracts hardhat
Install the dependencies:
yarn
Compile the contracts:
yarn compile
Run the tests:
yarn test
# or
yarn test-p # parallel mode
Run the coverage tests:
yarn coverage
Run the full pipeline (should be run before commiting code):
yarn run-all
See package.json
for additional commands.
Note: this repository uses git lfs: the module should be installed before pushing changes.