Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4c713f8cea | |||
| 7bb5592ad5 | |||
| 15c5c71795 | |||
| 4448c13c3c | |||
| 5420879d9b | |||
| 25edd3cd62 | |||
| 238d17cab9 | |||
| 5955d8e85b | |||
| 09329f8a18 | |||
| cbc6145f5f | |||
| 13d5e0466a | |||
| 7e814a3074 | |||
| a1d57bac50 | |||
| 11d65442b3 | |||
| dfef6a68ee | |||
| 0f10efe232 | |||
| 96b95592c3 | |||
| 8de6eba8a3 | |||
| 1642b6639b | |||
| 3ec4307c8a | |||
| f355bd3a2a | |||
| 3e1b25a5cf | |||
| f7b236dca8 | |||
| e5dbc7435e | |||
| 9a2e4cb3a7 | |||
| d095542fa4 | |||
| dff520afae | |||
| 2d05db171a | |||
| e919d96ff2 | |||
| 54c31ad98b | |||
| 5ad74c6d10 | |||
| c5d040beb9 | |||
| 30c3c6c16e | |||
| 147dc89054 | |||
| 7c6e289782 | |||
| d210847e28 | |||
| a290e13099 | |||
| 97bba5adaa | |||
| fbbaf3365b | |||
| 4147005b0c | |||
| 81dbe643a0 | |||
| 9cbe8b340c | |||
| 3c80a42866 | |||
| e2d2ebc8fc | |||
| bc8f442d00 | |||
| 4a9db80cb9 | |||
| 887985413c | |||
| b18cf4ba42 | |||
| 39a752e398 | |||
| 6ff283bebc | |||
| 1cf4db9615 |
5
.changeset/angry-ties-switch.md
Normal file
5
.changeset/angry-ties-switch.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`TimelockController`: Changed the role architecture to use `DEFAULT_ADMIN_ROLE` as the admin for all roles, instead of the bespoke `TIMELOCK_ADMIN_ROLE` that was used previously. This aligns with the general recommendation for `AccessControl` and makes the addition of new roles easier. Accordingly, the `admin` parameter and timelock will now be granted `DEFAULT_ADMIN_ROLE` instead of `TIMELOCK_ADMIN_ROLE`. ([#3799](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3799))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Initializable`: optimize `_disableInitializers` by using `!=` instead of `<`. ([#3787](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3787))
|
||||
5
.changeset/beige-ducks-flow.md
Normal file
5
.changeset/beige-ducks-flow.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Remove deprecated GovernorProposalThreshold module.
|
||||
5
.changeset/bright-tomatoes-sing.md
Normal file
5
.changeset/bright-tomatoes-sing.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC20`, `ERC1155`: Deleted `_beforeTokenTransfer` and `_afterTokenTransfer` hooks, added a new internal `_update` function for customizations, and refactored all extensions using those hooks to use `_update` instead. ([#3838](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3838), [#3876](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3876))
|
||||
5
.changeset/chilled-spiders-attack.md
Normal file
5
.changeset/chilled-spiders-attack.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC1155Supply`: add a `totalSupply()` function that returns the total amount of token circulating, this change will restrict the total tokens minted across all ids to 2\*\*256-1 .
|
||||
5
.changeset/clever-pumas-beg.md
Normal file
5
.changeset/clever-pumas-beg.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Ownable`: Add an `initialOwner` parameter to the constructor, making the ownership initialization explicit.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ReentrancyGuard`: Add a `_reentrancyGuardEntered` function to expose the guard status. ([#3714](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3714))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Ownable2Step`: make `acceptOwnership` public virtual to enable usecases that require overriding it. ([#3960](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3960))
|
||||
5
.changeset/dirty-mangos-sort.md
Normal file
5
.changeset/dirty-mangos-sort.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Removed presets in favor of [OpenZeppelin Contracts Wizard](https://wizard.openzeppelin.com/).
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ERC721Wrapper`: add a new extension of the `ERC721` token which wraps an underlying token. Deposit and withdraw guarantee that the ownership of each token is backed by a corresponding underlying token with the same identifier.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`EnumerableMap`: add a `keys()` function that returns an array containing all the keys. ([#3920](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3920))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`UUPSUpgradeable.sol`: Change visibility to the functions `upgradeTo ` and `upgradeToAndCall ` from `external` to `public`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`TimelockController`: Add the `CallSalt` event to emit on operation schedule.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Governor`: add a public `cancel(uint256)` function.
|
||||
5
.changeset/fluffy-gifts-build.md
Normal file
5
.changeset/fluffy-gifts-build.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Remove ERC1820Implementer.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Governor`: Enable timestamp operation for blockchains without a stable block time. This is achieved by connecting a Governor's internal clock to match a voting token's EIP-6372 interface.
|
||||
5
.changeset/fresh-birds-kiss.md
Normal file
5
.changeset/fresh-birds-kiss.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Checkpoints`: library moved from `utils` to `utils/structs`
|
||||
5
.changeset/friendly-suits-camp.md
Normal file
5
.changeset/friendly-suits-camp.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Remove Checkpoints.History.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
Reformatted codebase with latest version of Prettier Solidity. ([#3898](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3898))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Strings`: add `equal` method. ([#3774](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3774))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`IERC5313`: Add an interface for EIP-5313 that is now final.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Math`: optimize `log256` rounding check. ([#3745](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3745))
|
||||
5
.changeset/hungry-impalas-perform.md
Normal file
5
.changeset/hungry-impalas-perform.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC165Storage`: Removed this contract in favor of inheritance based approach. ([#3880](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3880))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ERC20Votes`: optimize by using unchecked arithmetic. ([#3748](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3748))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Multicall`: annotate `multicall` function as upgrade safe to not raise a flag for its delegatecall. ([#3961](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3961))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`IERC4906`: Add an interface for ERC-4906 that is now Final.
|
||||
5
.changeset/mean-walls-watch.md
Normal file
5
.changeset/mean-walls-watch.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`Nonces`: Added a new contract to keep track of user nonces. Used for signatures in `ERC20Permit`, `ERC20Votes`, and `ERC721Votes`. ([#3816](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3816))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`StorageSlot`: Add support for `string` and `bytes`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ERC20Pausable`, `ERC721Pausable`, `ERC1155Pausable`: Add note regarding missing public pausing functionality
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Votes`, `ERC20Votes`, `ERC721Votes`: support timestamp checkpointing using EIP-6372.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ERC4626`: Add mitigation to the inflation attack through virtual shares and assets.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`Strings`: add `toString` method for signed integers. ([#3773](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3773))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ERC20Wrapper`: Make the `underlying` variable private and add a public accessor.
|
||||
5
.changeset/rotten-insects-wash.md
Normal file
5
.changeset/rotten-insects-wash.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ProxyAdmin`: Removed `getProxyAdmin` and `getProxyImplementation` getters. ([#3820](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3820))
|
||||
5
.changeset/selfish-queens-rest.md
Normal file
5
.changeset/selfish-queens-rest.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Remove PullPayment and Escrow contracts (Escrow, ConditionalEscrow, RefundEscrow).
|
||||
5
.changeset/short-eels-enjoy.md
Normal file
5
.changeset/short-eels-enjoy.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Bump minimum compiler version required to 0.8.19
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`EIP712`: add EIP-5267 support for better domain discovery.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`AccessControlDefaultAdminRules`: Add an extension of `AccessControl` with additional security rules for the `DEFAULT_ADMIN_ROLE`.
|
||||
5
.changeset/silly-bees-beam.md
Normal file
5
.changeset/silly-bees-beam.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC20Votes`: Changed internal vote accounting to reusable `Votes` module previously used by `ERC721Votes`. Removed implicit `ERC20Permit` inheritance. [#3816](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3816)
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`SignatureChecker`: Add `isValidERC1271SignatureNow` for checking a signature directly against a smart contract using ERC-1271.
|
||||
5
.changeset/slimy-penguins-attack.md
Normal file
5
.changeset/slimy-penguins-attack.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`TransparentUpgradeableProxy`: Removed `admin` and `implementation` getters, which were only callable by the proxy owner and thus not very useful. ([#3820](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3820))
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ECDSA`: Add a function `toDataWithIntendedValidatorHash` that encodes data with version 0x00 following EIP-191.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`SafeERC20`: Add a `forceApprove` function to improve compatibility with tokens behaving like USDT.
|
||||
5
.changeset/smooth-books-wink.md
Normal file
5
.changeset/smooth-books-wink.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`ERC1155`: Remove check for address zero in `balanceOf`.
|
||||
5
.changeset/spicy-ducks-cough.md
Normal file
5
.changeset/spicy-ducks-cough.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Remove the Timers library.
|
||||
5
.changeset/spotty-hotels-type.md
Normal file
5
.changeset/spotty-hotels-type.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`ERC721Consecutive`: Add a `_firstConsecutiveId` internal function that can be overridden to change the id of the first token minted through `_mintConsecutive`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ERC1967Upgrade`: removed contract-wide `oz-upgrades-unsafe-allow delegatecall` annotation, replaced by granular annotation in `UUPSUpgradeable`.
|
||||
5
.changeset/swift-berries-sort.md
Normal file
5
.changeset/swift-berries-sort.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Remove ERC777 implementation.
|
||||
5
.changeset/tame-geckos-search.md
Normal file
5
.changeset/tame-geckos-search.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Remove SafeMath and SignedSafeMath libraries.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`MerkleProof`: optimize by using unchecked arithmetic. ([#3745](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3745))
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ERC20Wrapper`: self wrapping and deposit by the wrapper itself are now explicitelly forbiden.
|
||||
|
||||
commit: 3214f6c25
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ECDSA`: optimize bytes32 computation by using assembly instead of `abi.encodePacked`.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ERC721URIStorage`: Emit ERC-4906 `MetadataUpdate` in `_setTokenURI`.
|
||||
5
.changeset/three-weeks-double.md
Normal file
5
.changeset/three-weeks-double.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
Remove CrossChain contracts, including AccessControlCrossChain and all the vendored bridge interfaces.
|
||||
5
.changeset/unlucky-snakes-drive.md
Normal file
5
.changeset/unlucky-snakes-drive.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': patch
|
||||
---
|
||||
|
||||
`Address`: Removed `isContract` because of its ambiguous nature and potential for misuse.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`ShortStrings`: Added a library for handling short strings in a gas efficient way, with fallback to storage for longer strings.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`SignatureChecker`: Allow return data length greater than 32 from EIP-1271 signers.
|
||||
5
.changeset/wild-windows-trade.md
Normal file
5
.changeset/wild-windows-trade.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'openzeppelin-solidity': major
|
||||
---
|
||||
|
||||
`SafeERC20`: Refactor `safeDecreaseAllowance` and `safeIncreaseAllowance` to support USDT-like tokens.
|
||||
@ -1,5 +0,0 @@
|
||||
---
|
||||
'openzeppelin-solidity': minor
|
||||
---
|
||||
|
||||
`UUPSUpgradeable`: added granular `oz-upgrades-unsafe-allow-reachable` annotation to improve upgrade safety checks on latest version of the Upgrades Plugins (starting with `@openzeppelin/upgrades-core@1.21.0`).
|
||||
4
.github/workflows/checks.yml
vendored
4
.github/workflows/checks.yml
vendored
@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- next-v*
|
||||
- release-v*
|
||||
pull_request: {}
|
||||
workflow_dispatch: {}
|
||||
@ -107,7 +108,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run CodeSpell
|
||||
uses: codespell-project/actions-codespell@v1.0
|
||||
uses: codespell-project/actions-codespell@v2.0
|
||||
with:
|
||||
check_hidden: true
|
||||
check_filenames: true
|
||||
skip: package-lock.json,*.pdf
|
||||
|
||||
81
CHANGELOG.md
81
CHANGELOG.md
@ -1,5 +1,86 @@
|
||||
# Changelog
|
||||
|
||||
### Removals
|
||||
|
||||
The following contracts were removed:
|
||||
|
||||
- `ERC20Snapshot`
|
||||
- `ERC20VotesComp`
|
||||
- `GovernorVotesComp`
|
||||
- `PaymentSplitter`
|
||||
- `TokenTimelock` (removed in favor of `VestingWallet`)
|
||||
|
||||
### How to upgrade from 4.x
|
||||
|
||||
#### ERC20, ERC721, and ERC1155
|
||||
|
||||
These breaking changes will require modifications to ERC20, ERC721, and ERC1155 contracts, since the `_afterTokenTransfer` and `_beforeTokenTransfer` functions were removed. Any customization made through those hooks should now be done overriding the new `_update` function instead.
|
||||
|
||||
Minting and burning are implemented by `_update` and customizations should be done by overriding this function as well. `_mint` and `_burn` are no longer virtual (meaning they are not overridable) to guard against possible inconsistencies.
|
||||
|
||||
For example, a contract using `ERC20`'s `_beforeTokenTransfer` hook would have to be changed in the following way.
|
||||
|
||||
```diff
|
||||
- function _beforeTokenTransfer(
|
||||
+ function _update(
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount
|
||||
) internal virtual override {
|
||||
- super._beforeTokenTransfer(from, to, amount);
|
||||
require(!condition(), "ERC20: wrong condition");
|
||||
+ super._update(from, to, amount);
|
||||
}
|
||||
```
|
||||
|
||||
#### ERC165Storage
|
||||
|
||||
Users that were registering EIP-165 interfaces with `_registerInterface` from `ERC165Storage` should instead do so so by overriding the `supportsInterface` function as seen below:
|
||||
|
||||
```solidity
|
||||
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
|
||||
return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
|
||||
}
|
||||
```
|
||||
|
||||
## 4.9.0 (2023-05-23)
|
||||
|
||||
- `ReentrancyGuard`: Add a `_reentrancyGuardEntered` function to expose the guard status. ([#3714](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3714))
|
||||
- `ERC721Wrapper`: add a new extension of the `ERC721` token which wraps an underlying token. Deposit and withdraw guarantee that the ownership of each token is backed by a corresponding underlying token with the same identifier. ([#3863](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3863))
|
||||
- `EnumerableMap`: add a `keys()` function that returns an array containing all the keys. ([#3920](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3920))
|
||||
- `Governor`: add a public `cancel(uint256)` function. ([#3983](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3983))
|
||||
- `Governor`: Enable timestamp operation for blockchains without a stable block time. This is achieved by connecting a Governor's internal clock to match a voting token's EIP-6372 interface. ([#3934](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3934))
|
||||
- `Strings`: add `equal` method. ([#3774](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3774))
|
||||
- `IERC5313`: Add an interface for EIP-5313 that is now final. ([#4013](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4013))
|
||||
- `IERC4906`: Add an interface for ERC-4906 that is now Final. ([#4012](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4012))
|
||||
- `StorageSlot`: Add support for `string` and `bytes`. ([#4008](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4008))
|
||||
- `Votes`, `ERC20Votes`, `ERC721Votes`: support timestamp checkpointing using EIP-6372. ([#3934](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3934))
|
||||
- `ERC4626`: Add mitigation to the inflation attack through virtual shares and assets. ([#3979](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3979))
|
||||
- `Strings`: add `toString` method for signed integers. ([#3773](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3773))
|
||||
- `ERC20Wrapper`: Make the `underlying` variable private and add a public accessor. ([#4029](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4029))
|
||||
- `EIP712`: add EIP-5267 support for better domain discovery. ([#3969](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3969))
|
||||
- `AccessControlDefaultAdminRules`: Add an extension of `AccessControl` with additional security rules for the `DEFAULT_ADMIN_ROLE`. ([#4009](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4009))
|
||||
- `SignatureChecker`: Add `isValidERC1271SignatureNow` for checking a signature directly against a smart contract using ERC-1271. ([#3932](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3932))
|
||||
- `SafeERC20`: Add a `forceApprove` function to improve compatibility with tokens behaving like USDT. ([#4067](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4067))
|
||||
- `ERC1967Upgrade`: removed contract-wide `oz-upgrades-unsafe-allow delegatecall` annotation, replaced by granular annotation in `UUPSUpgradeable`. ([#3971](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3971))
|
||||
- `ERC20Wrapper`: self wrapping and deposit by the wrapper itself are now explicitly forbidden. ([#4100](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4100))
|
||||
- `ECDSA`: optimize bytes32 computation by using assembly instead of `abi.encodePacked`. ([#3853](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3853))
|
||||
- `ERC721URIStorage`: Emit ERC-4906 `MetadataUpdate` in `_setTokenURI`. ([#4012](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4012))
|
||||
- `ShortStrings`: Added a library for handling short strings in a gas efficient way, with fallback to storage for longer strings. ([#4023](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4023))
|
||||
- `SignatureChecker`: Allow return data length greater than 32 from EIP-1271 signers. ([#4038](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4038))
|
||||
- `UUPSUpgradeable`: added granular `oz-upgrades-unsafe-allow-reachable` annotation to improve upgrade safety checks on latest version of the Upgrades Plugins (starting with `@openzeppelin/upgrades-core@1.21.0`). ([#3971](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3971))
|
||||
- `Initializable`: optimize `_disableInitializers` by using `!=` instead of `<`. ([#3787](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3787))
|
||||
- `Ownable2Step`: make `acceptOwnership` public virtual to enable usecases that require overriding it. ([#3960](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3960))
|
||||
- `UUPSUpgradeable.sol`: Change visibility to the functions `upgradeTo ` and `upgradeToAndCall ` from `external` to `public`. ([#3959](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3959))
|
||||
- `TimelockController`: Add the `CallSalt` event to emit on operation schedule. ([#4001](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4001))
|
||||
- Reformatted codebase with latest version of Prettier Solidity. ([#3898](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3898))
|
||||
- `Math`: optimize `log256` rounding check. ([#3745](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3745))
|
||||
- `ERC20Votes`: optimize by using unchecked arithmetic. ([#3748](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3748))
|
||||
- `Multicall`: annotate `multicall` function as upgrade safe to not raise a flag for its delegatecall. ([#3961](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3961))
|
||||
- `ERC20Pausable`, `ERC721Pausable`, `ERC1155Pausable`: Add note regarding missing public pausing functionality ([#4007](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4007))
|
||||
- `ECDSA`: Add a function `toDataWithIntendedValidatorHash` that encodes data with version 0x00 following EIP-191. ([#4063](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4063))
|
||||
- `MerkleProof`: optimize by using unchecked arithmetic. ([#3745](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3745))
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- `EIP712`: Addition of ERC5267 support requires support for user defined value types, which was released in Solidity version 0.8.8. This requires a pragma change from `^0.8.0` to `^0.8.8`.
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
> **Warning**
|
||||
> Version 5.0 is under active development. The code in this branch is not recommended for use.
|
||||
|
||||
# <img src="logo.svg" alt="OpenZeppelin" height="40px">
|
||||
|
||||
[](https://www.npmjs.org/package/@openzeppelin/contracts)
|
||||
@ -33,7 +36,7 @@ An alternative to npm is to use the GitHub repository (`openzeppelin/openzeppeli
|
||||
Once installed, you can use the contracts in the library by importing them:
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
||||
|
||||
|
||||
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/access/AccessControlDefaultAdminRules.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/access/AccessControl.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/utils/structs/DoubleEndedQueue.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/token/ERC20/ERC20.sol";
|
||||
import "../patched/token/ERC20/extensions/ERC20Permit.sol";
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/token/ERC20/extensions/ERC20Permit.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/token/ERC20/extensions/ERC20Wrapper.sol";
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
import "../patched/interfaces/IERC3156FlashBorrower.sol";
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
contract ERC3156FlashBorrowerHarness is IERC3156FlashBorrower {
|
||||
bytes32 somethingToReturn;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/token/ERC721/ERC721.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/interfaces/IERC721Receiver.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/utils/structs/EnumerableMap.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/utils/structs/EnumerableSet.sol";
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.2;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/proxy/utils/Initializable.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/access/Ownable2Step.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/access/Ownable.sol";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/security/Pausable.sol";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../patched/governance/TimelockController.sol";
|
||||
|
||||
|
||||
@ -12,44 +12,23 @@ use rule onlyGrantCanGrant filtered {
|
||||
│ Helpers │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
definition timeSanity(env e) returns bool =
|
||||
e.block.timestamp > 0 && e.block.timestamp + defaultAdminDelay(e) < max_uint48();
|
||||
|
||||
function max_uint48() returns mathint {
|
||||
return (1 << 48) - 1;
|
||||
}
|
||||
definition delayChangeWaitSanity(env e, uint48 newDelay) returns bool =
|
||||
e.block.timestamp + delayChangeWait_(e, newDelay) < max_uint48();
|
||||
|
||||
function nonZeroAccount(address account) returns bool {
|
||||
return account != 0;
|
||||
}
|
||||
definition isSet(uint48 schedule) returns bool =
|
||||
schedule != 0;
|
||||
|
||||
function timeSanity(env e) returns bool {
|
||||
return
|
||||
e.block.timestamp > 0 && // Avoids 0 schedules
|
||||
e.block.timestamp + defaultAdminDelay(e) < max_uint48();
|
||||
}
|
||||
definition hasPassed(env e, uint48 schedule) returns bool =
|
||||
schedule < e.block.timestamp;
|
||||
|
||||
function delayChangeWaitSanity(env e, uint48 newDelay) returns bool {
|
||||
return e.block.timestamp + delayChangeWait_(e, newDelay) < max_uint48();
|
||||
}
|
||||
definition increasingDelaySchedule(env e, uint48 newDelay) returns mathint =
|
||||
e.block.timestamp + min(newDelay, defaultAdminDelayIncreaseWait());
|
||||
|
||||
function isSet(uint48 schedule) returns bool {
|
||||
return schedule != 0;
|
||||
}
|
||||
|
||||
function hasPassed(env e, uint48 schedule) returns bool {
|
||||
return schedule < e.block.timestamp;
|
||||
}
|
||||
|
||||
function min(uint48 a, uint48 b) returns mathint {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
function increasingDelaySchedule(env e, uint48 newDelay) returns mathint {
|
||||
return e.block.timestamp + min(newDelay, defaultAdminDelayIncreaseWait());
|
||||
}
|
||||
|
||||
function decreasingDelaySchedule(env e, uint48 newDelay) returns mathint {
|
||||
return e.block.timestamp + defaultAdminDelay(e) - newDelay;
|
||||
}
|
||||
definition decreasingDelaySchedule(env e, uint48 newDelay) returns mathint =
|
||||
e.block.timestamp + defaultAdminDelay(e) - newDelay;
|
||||
|
||||
/*
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
@ -57,11 +36,10 @@ function decreasingDelaySchedule(env e, uint48 newDelay) returns mathint {
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
invariant defaultAdminConsistency(address account)
|
||||
defaultAdmin() == account <=> hasRole(DEFAULT_ADMIN_ROLE(), account)
|
||||
(account == defaultAdmin() && account != 0) <=> hasRole(DEFAULT_ADMIN_ROLE(), account)
|
||||
{
|
||||
preserved {
|
||||
// defaultAdmin() returns the zero address when there's no default admin
|
||||
require nonZeroAccount(account);
|
||||
preserved with (env e) {
|
||||
require nonzerosender(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,10 +50,12 @@ invariant defaultAdminConsistency(address account)
|
||||
*/
|
||||
invariant singleDefaultAdmin(address account, address another)
|
||||
hasRole(DEFAULT_ADMIN_ROLE(), account) && hasRole(DEFAULT_ADMIN_ROLE(), another) => another == account
|
||||
// We filter here because we couldn't find a way to force Certora to have an initial state with
|
||||
// only one DEFAULT_ADMIN_ROLE enforced, so a counter example is a different default admin since inception
|
||||
// triggering the transfer, which is known to be impossible by definition.
|
||||
filtered { f -> f.selector != acceptDefaultAdminTransfer().selector }
|
||||
{
|
||||
preserved {
|
||||
requireInvariant defaultAdminConsistency(account);
|
||||
requireInvariant defaultAdminConsistency(another);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
@ -118,7 +98,8 @@ rule revokeRoleEffect(env e, bytes32 role) {
|
||||
"roles can only be revoked by their owner except for the default admin role";
|
||||
|
||||
// effect
|
||||
assert success => !hasRole(role, account), "role is revoked";
|
||||
assert success => !hasRole(role, account),
|
||||
"role is revoked";
|
||||
|
||||
// no side effect
|
||||
assert hasOtherRoleBefore != hasOtherRoleAfter => (role == otherRole && account == otherAccount),
|
||||
@ -137,35 +118,59 @@ rule renounceRoleEffect(env e, bytes32 role) {
|
||||
address account;
|
||||
address otherAccount;
|
||||
|
||||
bool hasOtherRoleBefore = hasRole(otherRole, otherAccount);
|
||||
uint48 scheduleBefore = pendingDefaultAdminSchedule_();
|
||||
bool hasOtherRoleBefore = hasRole(otherRole, otherAccount);
|
||||
address adminBefore = defaultAdmin();
|
||||
address pendingAdminBefore = pendingDefaultAdmin_();
|
||||
uint48 scheduleBefore = pendingDefaultAdminSchedule_();
|
||||
|
||||
renounceRole@withrevert(e, role, account);
|
||||
bool success = !lastReverted;
|
||||
|
||||
bool hasOtherRoleAfter = hasRole(otherRole, otherAccount);
|
||||
bool hasOtherRoleAfter = hasRole(otherRole, otherAccount);
|
||||
address adminAfter = defaultAdmin();
|
||||
address pendingAdminAfter = pendingDefaultAdmin_();
|
||||
uint48 scheduleAfter = pendingDefaultAdminSchedule_();
|
||||
|
||||
// liveness
|
||||
assert success <=> (
|
||||
account == e.msg.sender &&
|
||||
(
|
||||
role != DEFAULT_ADMIN_ROLE() ||
|
||||
account != adminBefore ||
|
||||
(
|
||||
role != DEFAULT_ADMIN_ROLE()
|
||||
) || (
|
||||
role == DEFAULT_ADMIN_ROLE() &&
|
||||
pendingAdminBefore == 0 &&
|
||||
isSet(scheduleBefore) &&
|
||||
hasPassed(e, scheduleBefore)
|
||||
)
|
||||
)
|
||||
), "an account only can renounce by itself with a delay for the default admin role";
|
||||
),
|
||||
"an account only can renounce by itself with a delay for the default admin role";
|
||||
|
||||
// effect
|
||||
assert success => !hasRole(role, account), "role is renounced";
|
||||
assert success => !hasRole(role, account),
|
||||
"role is renounced";
|
||||
|
||||
assert success => (
|
||||
(
|
||||
role == DEFAULT_ADMIN_ROLE() &&
|
||||
account == adminBefore
|
||||
) ? (
|
||||
adminAfter == 0 &&
|
||||
pendingAdminAfter == 0 &&
|
||||
scheduleAfter == 0
|
||||
) : (
|
||||
adminAfter == adminBefore &&
|
||||
pendingAdminAfter == pendingAdminBefore &&
|
||||
scheduleAfter == scheduleBefore
|
||||
)
|
||||
),
|
||||
"renouncing default admin role cleans state iff called by previous admin";
|
||||
|
||||
// no side effect
|
||||
assert hasOtherRoleBefore != hasOtherRoleAfter => (role == otherRole && account == otherAccount),
|
||||
assert hasOtherRoleBefore != hasOtherRoleAfter => (
|
||||
role == otherRole &&
|
||||
account == otherAccount
|
||||
),
|
||||
"no other role is affected";
|
||||
}
|
||||
|
||||
@ -175,10 +180,6 @@ rule renounceRoleEffect(env e, bytes32 role) {
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
rule noDefaultAdminChange(env e, method f, calldataarg args) {
|
||||
require nonZeroAccount(e.msg.sender);
|
||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
||||
|
||||
address adminBefore = defaultAdmin();
|
||||
f(e, args);
|
||||
address adminAfter = defaultAdmin();
|
||||
@ -186,18 +187,17 @@ rule noDefaultAdminChange(env e, method f, calldataarg args) {
|
||||
assert adminBefore != adminAfter => (
|
||||
f.selector == acceptDefaultAdminTransfer().selector ||
|
||||
f.selector == renounceRole(bytes32,address).selector
|
||||
), "default admin is only affected by accepting an admin transfer or renoucing";
|
||||
),
|
||||
"default admin is only affected by accepting an admin transfer or renoucing";
|
||||
}
|
||||
|
||||
/*
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Rule: pendingDefaultAdmin is only affected by beginning, accepting or canceling an admin transfer │
|
||||
│ Rule: pendingDefaultAdmin is only affected by beginning, completing (accept or renounce), or canceling an admin │
|
||||
│ transfer │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
rule noPendingDefaultAdminChange(env e, method f, calldataarg args) {
|
||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
||||
|
||||
address pendingAdminBefore = pendingDefaultAdmin_();
|
||||
address scheduleBefore = pendingDefaultAdminSchedule_();
|
||||
f(e, args);
|
||||
@ -210,8 +210,10 @@ rule noPendingDefaultAdminChange(env e, method f, calldataarg args) {
|
||||
) => (
|
||||
f.selector == beginDefaultAdminTransfer(address).selector ||
|
||||
f.selector == acceptDefaultAdminTransfer().selector ||
|
||||
f.selector == cancelDefaultAdminTransfer().selector
|
||||
), "pending admin and its schedule is only affected by beginning, accepting or cancelling an admin transfer";
|
||||
f.selector == cancelDefaultAdminTransfer().selector ||
|
||||
f.selector == renounceRole(bytes32,address).selector
|
||||
),
|
||||
"pending admin and its schedule is only affected by beginning, completing, or cancelling an admin transfer";
|
||||
}
|
||||
|
||||
/*
|
||||
@ -224,7 +226,8 @@ rule noDefaultAdminDelayChange(env e, method f, calldataarg args) {
|
||||
f(e, args);
|
||||
uint48 delayAfter = defaultAdminDelay(e);
|
||||
|
||||
assert delayBefore == delayAfter, "delay can't be changed atomically by any function";
|
||||
assert delayBefore == delayAfter,
|
||||
"delay can't be changed atomically by any function";
|
||||
}
|
||||
|
||||
/*
|
||||
@ -240,7 +243,8 @@ rule noPendingDefaultAdminDelayChange(env e, method f, calldataarg args) {
|
||||
assert pendingDelayBefore != pendingDelayAfter => (
|
||||
f.selector == changeDefaultAdminDelay(uint48).selector ||
|
||||
f.selector == rollbackDefaultAdminDelay().selector
|
||||
), "pending delay is only affected by changeDefaultAdminDelay or rollbackDefaultAdminDelay";
|
||||
),
|
||||
"pending delay is only affected by changeDefaultAdminDelay or rollbackDefaultAdminDelay";
|
||||
}
|
||||
|
||||
/*
|
||||
@ -263,10 +267,10 @@ rule noDefaultAdminDelayIncreaseWaitChange(env e, method f, calldataarg args) {
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
rule beginDefaultAdminTransfer(env e, address newAdmin) {
|
||||
require nonpayable(e);
|
||||
require timeSanity(e);
|
||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
||||
require nonpayable(e);
|
||||
require nonzerosender(e);
|
||||
requireInvariant defaultAdminConsistency(e.msg.sender);
|
||||
|
||||
beginDefaultAdminTransfer@withrevert(e, newAdmin);
|
||||
bool success = !lastReverted;
|
||||
@ -288,18 +292,24 @@ rule beginDefaultAdminTransfer(env e, address newAdmin) {
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
rule pendingDefaultAdminDelayEnforced(env e1, env e2, method f, calldataarg args, address newAdmin) {
|
||||
require e1.block.timestamp < e2.block.timestamp;
|
||||
require e1.block.timestamp <= e2.block.timestamp;
|
||||
|
||||
uint48 delayBefore = defaultAdminDelay(e1);
|
||||
address adminBefore = defaultAdmin();
|
||||
|
||||
// There might be a better way to generalize this without requiring `beginDefaultAdminTransfer`, but currently
|
||||
// it's the only way in which we can attest that only `delayBefore` has passed before a change.
|
||||
beginDefaultAdminTransfer(e1, newAdmin);
|
||||
f(e2, args);
|
||||
|
||||
address adminAfter = defaultAdmin();
|
||||
|
||||
assert adminAfter == newAdmin => ((e2.block.timestamp >= e1.block.timestamp + delayBefore) || adminBefore == newAdmin),
|
||||
"A delay can't change in less than applied schedule";
|
||||
// change can only happen towards the newAdmin, with the delay
|
||||
assert adminAfter != adminBefore => (
|
||||
adminAfter == newAdmin &&
|
||||
e2.block.timestamp >= e1.block.timestamp + delayBefore
|
||||
),
|
||||
"The admin can only change after the enforced delay and to the previously scheduled new admin";
|
||||
}
|
||||
|
||||
/*
|
||||
@ -309,17 +319,19 @@ rule pendingDefaultAdminDelayEnforced(env e1, env e2, method f, calldataarg args
|
||||
*/
|
||||
rule acceptDefaultAdminTransfer(env e) {
|
||||
require nonpayable(e);
|
||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
||||
|
||||
address pendingAdminBefore = pendingDefaultAdmin_();
|
||||
uint48 scheduleAfter = pendingDefaultAdminSchedule_();
|
||||
uint48 scheduleBefore = pendingDefaultAdminSchedule_();
|
||||
|
||||
acceptDefaultAdminTransfer@withrevert(e);
|
||||
bool success = !lastReverted;
|
||||
|
||||
// liveness
|
||||
assert success <=> e.msg.sender == pendingAdminBefore && isSet(scheduleAfter) && hasPassed(e, scheduleAfter),
|
||||
assert success <=> (
|
||||
e.msg.sender == pendingAdminBefore &&
|
||||
isSet(scheduleBefore) &&
|
||||
hasPassed(e, scheduleBefore)
|
||||
),
|
||||
"only the pending default admin can accept the role after the schedule has been set and passed";
|
||||
|
||||
// effect
|
||||
@ -338,8 +350,8 @@ rule acceptDefaultAdminTransfer(env e) {
|
||||
*/
|
||||
rule cancelDefaultAdminTransfer(env e) {
|
||||
require nonpayable(e);
|
||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
||||
require nonzerosender(e);
|
||||
requireInvariant defaultAdminConsistency(e.msg.sender);
|
||||
|
||||
cancelDefaultAdminTransfer@withrevert(e);
|
||||
bool success = !lastReverted;
|
||||
@ -361,11 +373,11 @@ rule cancelDefaultAdminTransfer(env e) {
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
rule changeDefaultAdminDelay(env e, uint48 newDelay) {
|
||||
require nonpayable(e);
|
||||
require timeSanity(e);
|
||||
require nonpayable(e);
|
||||
require nonzerosender(e);
|
||||
require delayChangeWaitSanity(e, newDelay);
|
||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
||||
requireInvariant defaultAdminConsistency(e.msg.sender);
|
||||
|
||||
uint48 delayBefore = defaultAdminDelay(e);
|
||||
|
||||
@ -377,7 +389,9 @@ rule changeDefaultAdminDelay(env e, uint48 newDelay) {
|
||||
"only the current default admin can begin a delay change";
|
||||
|
||||
// effect
|
||||
assert success => pendingDelay_(e) == newDelay, "pending delay is set";
|
||||
assert success => pendingDelay_(e) == newDelay,
|
||||
"pending delay is set";
|
||||
|
||||
assert success => (
|
||||
pendingDelaySchedule_(e) > e.block.timestamp ||
|
||||
delayBefore == newDelay || // Interpreted as decreasing, x - x = 0
|
||||
@ -392,17 +406,22 @@ rule changeDefaultAdminDelay(env e, uint48 newDelay) {
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
rule pendingDelayWaitEnforced(env e1, env e2, method f, calldataarg args, uint48 newDelay) {
|
||||
require e1.block.timestamp < e2.block.timestamp;
|
||||
require e1.block.timestamp <= e2.block.timestamp;
|
||||
|
||||
uint48 delayBefore = defaultAdminDelay(e1);
|
||||
|
||||
changeDefaultAdminDelay(e1, newDelay);
|
||||
f(e2, args);
|
||||
|
||||
uint48 delayAfter = defaultAdminDelay(e2);
|
||||
|
||||
mathint delayWait = newDelay > delayBefore ? increasingDelaySchedule(e1, newDelay) : decreasingDelaySchedule(e1, newDelay);
|
||||
|
||||
assert delayAfter == newDelay => (e2.block.timestamp >= delayWait || delayBefore == newDelay),
|
||||
"A delay can't change in less than applied schedule";
|
||||
assert delayAfter != delayBefore => (
|
||||
delayAfter == newDelay &&
|
||||
e2.block.timestamp >= delayWait
|
||||
),
|
||||
"A delay can only change after the applied schedule";
|
||||
}
|
||||
|
||||
/*
|
||||
@ -427,8 +446,8 @@ rule pendingDelayWait(env e, uint48 newDelay) {
|
||||
*/
|
||||
rule rollbackDefaultAdminDelay(env e) {
|
||||
require nonpayable(e);
|
||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
||||
require nonzerosender(e);
|
||||
requireInvariant defaultAdminConsistency(e.msg.sender);
|
||||
|
||||
rollbackDefaultAdminDelay@withrevert(e);
|
||||
bool success = !lastReverted;
|
||||
@ -443,58 +462,3 @@ rule rollbackDefaultAdminDelay(env e) {
|
||||
assert success => pendingDelaySchedule_(e) == 0,
|
||||
"Pending default admin delay is reset";
|
||||
}
|
||||
|
||||
/*
|
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Rule: pending default admin and the delay can only change along with their corresponding schedules │
|
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
*/
|
||||
rule pendingValueAndScheduleCoupling(env e, address newAdmin, uint48 newDelay) {
|
||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
||||
|
||||
// Pending admin
|
||||
address pendingAdminBefore = pendingDefaultAdmin_();
|
||||
uint48 pendingAdminScheduleBefore = pendingDefaultAdminSchedule_();
|
||||
|
||||
beginDefaultAdminTransfer(e, newAdmin);
|
||||
|
||||
address pendingAdminAfter = pendingDefaultAdmin_();
|
||||
uint48 pendingAdminScheduleAfter = pendingDefaultAdminSchedule_();
|
||||
|
||||
assert (
|
||||
pendingAdminScheduleBefore != pendingDefaultAdminSchedule_() &&
|
||||
pendingAdminBefore == pendingAdminAfter
|
||||
) => newAdmin == pendingAdminBefore, "pending admin stays the same if the new admin set is the same";
|
||||
|
||||
assert (
|
||||
pendingAdminBefore != pendingAdminAfter &&
|
||||
pendingAdminScheduleBefore == pendingDefaultAdminSchedule_()
|
||||
) => (
|
||||
// Schedule doesn't change if:
|
||||
// - The defaultAdminDelay was reduced to a value such that added to the block.timestamp is equal to previous schedule
|
||||
e.block.timestamp + defaultAdminDelay(e) == pendingAdminScheduleBefore
|
||||
), "pending admin stays the same if a default admin transfer is begun on accepted edge cases";
|
||||
|
||||
// Pending delay
|
||||
address pendingDelayBefore = pendingDelay_(e);
|
||||
uint48 pendingDelayScheduleBefore = pendingDelaySchedule_(e);
|
||||
|
||||
changeDefaultAdminDelay(e, newDelay);
|
||||
|
||||
address pendingDelayAfter = pendingDelay_(e);
|
||||
uint48 pendingDelayScheduleAfter = pendingDelaySchedule_(e);
|
||||
|
||||
assert (
|
||||
pendingDelayScheduleBefore != pendingDelayScheduleAfter &&
|
||||
pendingDelayBefore == pendingDelayAfter
|
||||
) => newDelay == pendingDelayBefore || pendingDelayBefore == 0, "pending delay stays the same if the new delay set is the same";
|
||||
|
||||
assert (
|
||||
pendingDelayBefore != pendingDelayAfter &&
|
||||
pendingDelayScheduleBefore == pendingDelayScheduleAfter
|
||||
) => (
|
||||
increasingDelaySchedule(e, newDelay) == pendingDelayScheduleBefore ||
|
||||
decreasingDelaySchedule(e, newDelay) == pendingDelayScheduleBefore
|
||||
), "pending delay stays the same if a default admin transfer is begun on accepted edge cases";
|
||||
}
|
||||
|
||||
@ -1 +1,10 @@
|
||||
// environment
|
||||
definition nonpayable(env e) returns bool = e.msg.value == 0;
|
||||
definition nonzerosender(env e) returns bool = e.msg.sender != 0;
|
||||
|
||||
// constants
|
||||
definition max_uint48() returns mathint = (1 << 48) - 1;
|
||||
|
||||
// math
|
||||
definition min(mathint a, mathint b) returns mathint = a < b ? a : b;
|
||||
definition max(mathint a, mathint b) returns mathint = a > b ? a : b;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "./IAccessControl.sol";
|
||||
import "../utils/Context.sol";
|
||||
@ -183,30 +183,6 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
||||
_revokeRole(role, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Grants `role` to `account`.
|
||||
*
|
||||
* If `account` had not been already granted `role`, emits a {RoleGranted}
|
||||
* event. Note that unlike {grantRole}, this function doesn't perform any
|
||||
* checks on the calling account.
|
||||
*
|
||||
* May emit a {RoleGranted} event.
|
||||
*
|
||||
* [WARNING]
|
||||
* ====
|
||||
* This function should only be called from the constructor when setting
|
||||
* up the initial roles for the system.
|
||||
*
|
||||
* Using this function in any other way is effectively circumventing the admin
|
||||
* system imposed by {AccessControl}.
|
||||
* ====
|
||||
*
|
||||
* NOTE: This function is deprecated in favor of {_grantRole}.
|
||||
*/
|
||||
function _setupRole(bytes32 role, address account) internal virtual {
|
||||
_grantRole(role, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets `adminRole` as ``role``'s admin role.
|
||||
*
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControlCrossChain.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import "./AccessControl.sol";
|
||||
import "../crosschain/CrossChainEnabled.sol";
|
||||
|
||||
/**
|
||||
* @dev An extension to {AccessControl} with support for cross-chain access management.
|
||||
* For each role, is extension implements an equivalent "aliased" role that is used for
|
||||
* restricting calls originating from other chains.
|
||||
*
|
||||
* For example, if a function `myFunction` is protected by `onlyRole(SOME_ROLE)`, and
|
||||
* if an address `x` has role `SOME_ROLE`, it would be able to call `myFunction` directly.
|
||||
* A wallet or contract at the same address on another chain would however not be able
|
||||
* to call this function. In order to do so, it would require to have the role
|
||||
* `_crossChainRoleAlias(SOME_ROLE)`.
|
||||
*
|
||||
* This aliasing is required to protect against multiple contracts living at the same
|
||||
* address on different chains but controlled by conflicting entities.
|
||||
*
|
||||
* _Available since v4.6._
|
||||
*/
|
||||
abstract contract AccessControlCrossChain is AccessControl, CrossChainEnabled {
|
||||
bytes32 public constant CROSSCHAIN_ALIAS = keccak256("CROSSCHAIN_ALIAS");
|
||||
|
||||
/**
|
||||
* @dev See {AccessControl-_checkRole}.
|
||||
*/
|
||||
function _checkRole(bytes32 role) internal view virtual override {
|
||||
if (_isCrossChain()) {
|
||||
_checkRole(_crossChainRoleAlias(role), _crossChainSender());
|
||||
} else {
|
||||
super._checkRole(role);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the aliased role corresponding to `role`.
|
||||
*/
|
||||
function _crossChainRoleAlias(bytes32 role) internal pure virtual returns (bytes32) {
|
||||
return role ^ CROSSCHAIN_ALIAS;
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControlDefaultAdminRules.sol)
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControlDefaultAdminRules.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "./AccessControl.sol";
|
||||
import "./IAccessControlDefaultAdminRules.sol";
|
||||
@ -106,12 +106,13 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
|
||||
* non-administrated role.
|
||||
*/
|
||||
function renounceRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {
|
||||
if (role == DEFAULT_ADMIN_ROLE) {
|
||||
if (role == DEFAULT_ADMIN_ROLE && account == defaultAdmin()) {
|
||||
(address newDefaultAdmin, uint48 schedule) = pendingDefaultAdmin();
|
||||
require(
|
||||
newDefaultAdmin == address(0) && _isScheduleSet(schedule) && _hasSchedulePassed(schedule),
|
||||
"AccessControl: only can renounce in two delayed steps"
|
||||
);
|
||||
delete _pendingDefaultAdminSchedule;
|
||||
}
|
||||
super.renounceRole(role, account);
|
||||
}
|
||||
@ -137,7 +138,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
|
||||
* @dev See {AccessControl-_revokeRole}.
|
||||
*/
|
||||
function _revokeRole(bytes32 role, address account) internal virtual override {
|
||||
if (role == DEFAULT_ADMIN_ROLE && account == _currentDefaultAdmin) {
|
||||
if (role == DEFAULT_ADMIN_ROLE && account == defaultAdmin()) {
|
||||
delete _currentDefaultAdmin;
|
||||
}
|
||||
super._revokeRole(role, account);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "./IAccessControlEnumerable.sol";
|
||||
import "./AccessControl.sol";
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
/**
|
||||
* @dev External interface of AccessControl declared to support ERC165 detection.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.9.0 (access/IAccessControlDefaultAdminRules.sol)
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/IAccessControlDefaultAdminRules.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "./IAccessControl.sol";
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "./IAccessControl.sol";
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "../utils/Context.sol";
|
||||
|
||||
@ -25,8 +25,8 @@ abstract contract Ownable is Context {
|
||||
/**
|
||||
* @dev Initializes the contract setting the deployer as the initial owner.
|
||||
*/
|
||||
constructor() {
|
||||
_transferOwnership(_msgSender());
|
||||
constructor(address initialOwner) {
|
||||
_transferOwnership(initialOwner);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)
|
||||
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "./Ownable.sol";
|
||||
|
||||
|
||||
@ -18,8 +18,6 @@ This directory provides ways to restrict who can access the functions of a contr
|
||||
|
||||
{{AccessControl}}
|
||||
|
||||
{{AccessControlCrossChain}}
|
||||
|
||||
{{IAccessControlEnumerable}}
|
||||
|
||||
{{AccessControlEnumerable}}
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/CrossChainEnabled.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import "./errors.sol";
|
||||
|
||||
/**
|
||||
* @dev Provides information for building cross-chain aware contracts. This
|
||||
* abstract contract provides accessors and modifiers to control the execution
|
||||
* flow when receiving cross-chain messages.
|
||||
*
|
||||
* Actual implementations of cross-chain aware contracts, which are based on
|
||||
* this abstraction, will have to inherit from a bridge-specific
|
||||
* specialization. Such specializations are provided under
|
||||
* `crosschain/<chain>/CrossChainEnabled<chain>.sol`.
|
||||
*
|
||||
* _Available since v4.6._
|
||||
*/
|
||||
abstract contract CrossChainEnabled {
|
||||
/**
|
||||
* @dev Throws if the current function call is not the result of a
|
||||
* cross-chain execution.
|
||||
*/
|
||||
modifier onlyCrossChain() {
|
||||
if (!_isCrossChain()) revert NotCrossChainCall();
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Throws if the current function call is not the result of a
|
||||
* cross-chain execution initiated by `account`.
|
||||
*/
|
||||
modifier onlyCrossChainSender(address expected) {
|
||||
address actual = _crossChainSender();
|
||||
if (expected != actual) revert InvalidCrossChainSender(actual, expected);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns whether the current function call is the result of a
|
||||
* cross-chain message.
|
||||
*/
|
||||
function _isCrossChain() internal view virtual returns (bool);
|
||||
|
||||
/**
|
||||
* @dev Returns the address of the sender of the cross-chain message that
|
||||
* triggered the current function call.
|
||||
*
|
||||
* IMPORTANT: Should revert with `NotCrossChainCall` if the current function
|
||||
* call is not the result of a cross-chain message.
|
||||
*/
|
||||
function _crossChainSender() internal view virtual returns (address);
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
= Cross Chain Awareness
|
||||
|
||||
[.readme-notice]
|
||||
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/crosschain
|
||||
|
||||
This directory provides building blocks to improve cross-chain awareness of smart contracts.
|
||||
|
||||
- {CrossChainEnabled} is an abstraction that contains accessors and modifiers to control the execution flow when receiving cross-chain messages.
|
||||
|
||||
== CrossChainEnabled specializations
|
||||
|
||||
The following specializations of {CrossChainEnabled} provide implementations of the {CrossChainEnabled} abstraction for specific bridges. This can be used to complex cross-chain aware components such as {AccessControlCrossChain}.
|
||||
|
||||
{{CrossChainEnabledAMB}}
|
||||
|
||||
{{CrossChainEnabledArbitrumL1}}
|
||||
|
||||
{{CrossChainEnabledArbitrumL2}}
|
||||
|
||||
{{CrossChainEnabledOptimism}}
|
||||
|
||||
{{CrossChainEnabledPolygonChild}}
|
||||
|
||||
== Libraries for cross-chain
|
||||
|
||||
In addition to the {CrossChainEnabled} abstraction, cross-chain awareness is also available through libraries. These libraries can be used to build complex designs such as contracts with the ability to interact with multiple bridges.
|
||||
|
||||
{{LibAMB}}
|
||||
|
||||
{{LibArbitrumL1}}
|
||||
|
||||
{{LibArbitrumL2}}
|
||||
|
||||
{{LibOptimism}}
|
||||
@ -1,49 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/amb/CrossChainEnabledAMB.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import "../CrossChainEnabled.sol";
|
||||
import "./LibAMB.sol";
|
||||
|
||||
/**
|
||||
* @dev https://docs.tokenbridge.net/amb-bridge/about-amb-bridge[AMB]
|
||||
* specialization or the {CrossChainEnabled} abstraction.
|
||||
*
|
||||
* As of february 2020, AMB bridges are available between the following chains:
|
||||
*
|
||||
* - https://docs.tokenbridge.net/eth-xdai-amb-bridge/about-the-eth-xdai-amb[ETH ⇌ xDai]
|
||||
* - https://docs.tokenbridge.net/eth-qdai-bridge/about-the-eth-qdai-amb[ETH ⇌ qDai]
|
||||
* - https://docs.tokenbridge.net/eth-etc-amb-bridge/about-the-eth-etc-amb[ETH ⇌ ETC]
|
||||
* - https://docs.tokenbridge.net/eth-bsc-amb/about-the-eth-bsc-amb[ETH ⇌ BSC]
|
||||
* - https://docs.tokenbridge.net/eth-poa-amb-bridge/about-the-eth-poa-amb[ETH ⇌ POA]
|
||||
* - https://docs.tokenbridge.net/bsc-xdai-amb/about-the-bsc-xdai-amb[BSC ⇌ xDai]
|
||||
* - https://docs.tokenbridge.net/poa-xdai-amb/about-the-poa-xdai-amb[POA ⇌ xDai]
|
||||
* - https://docs.tokenbridge.net/rinkeby-xdai-amb-bridge/about-the-rinkeby-xdai-amb[Rinkeby ⇌ xDai]
|
||||
* - https://docs.tokenbridge.net/kovan-sokol-amb-bridge/about-the-kovan-sokol-amb[Kovan ⇌ Sokol]
|
||||
*
|
||||
* _Available since v4.6._
|
||||
*/
|
||||
contract CrossChainEnabledAMB is CrossChainEnabled {
|
||||
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
||||
address private immutable _bridge;
|
||||
|
||||
/// @custom:oz-upgrades-unsafe-allow constructor
|
||||
constructor(address bridge) {
|
||||
_bridge = bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev see {CrossChainEnabled-_isCrossChain}
|
||||
*/
|
||||
function _isCrossChain() internal view virtual override returns (bool) {
|
||||
return LibAMB.isCrossChain(_bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev see {CrossChainEnabled-_crossChainSender}
|
||||
*/
|
||||
function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
|
||||
return LibAMB.crossChainSender(_bridge);
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/amb/LibAMB.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import {IAMB as AMB_Bridge} from "../../vendor/amb/IAMB.sol";
|
||||
import "../errors.sol";
|
||||
|
||||
/**
|
||||
* @dev Primitives for cross-chain aware contracts using the
|
||||
* https://docs.tokenbridge.net/amb-bridge/about-amb-bridge[AMB]
|
||||
* family of bridges.
|
||||
*/
|
||||
library LibAMB {
|
||||
/**
|
||||
* @dev Returns whether the current function call is the result of a
|
||||
* cross-chain message relayed by `bridge`.
|
||||
*/
|
||||
function isCrossChain(address bridge) internal view returns (bool) {
|
||||
return msg.sender == bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the address of the sender that triggered the current
|
||||
* cross-chain message through `bridge`.
|
||||
*
|
||||
* NOTE: {isCrossChain} should be checked before trying to recover the
|
||||
* sender, as it will revert with `NotCrossChainCall` if the current
|
||||
* function call is not the result of a cross-chain message.
|
||||
*/
|
||||
function crossChainSender(address bridge) internal view returns (address) {
|
||||
if (!isCrossChain(bridge)) revert NotCrossChainCall();
|
||||
return AMB_Bridge(bridge).messageSender();
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import "../CrossChainEnabled.sol";
|
||||
import "./LibArbitrumL1.sol";
|
||||
|
||||
/**
|
||||
* @dev https://arbitrum.io/[Arbitrum] specialization or the
|
||||
* {CrossChainEnabled} abstraction the L1 side (mainnet).
|
||||
*
|
||||
* This version should only be deployed on L1 to process cross-chain messages
|
||||
* originating from L2. For the other side, use {CrossChainEnabledArbitrumL2}.
|
||||
*
|
||||
* The bridge contract is provided and maintained by the arbitrum team. You can
|
||||
* find the address of this contract on the rinkeby testnet in
|
||||
* https://developer.offchainlabs.com/docs/useful_addresses[Arbitrum's developer documentation].
|
||||
*
|
||||
* _Available since v4.6._
|
||||
*/
|
||||
abstract contract CrossChainEnabledArbitrumL1 is CrossChainEnabled {
|
||||
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
||||
address private immutable _bridge;
|
||||
|
||||
/// @custom:oz-upgrades-unsafe-allow constructor
|
||||
constructor(address bridge) {
|
||||
_bridge = bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev see {CrossChainEnabled-_isCrossChain}
|
||||
*/
|
||||
function _isCrossChain() internal view virtual override returns (bool) {
|
||||
return LibArbitrumL1.isCrossChain(_bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev see {CrossChainEnabled-_crossChainSender}
|
||||
*/
|
||||
function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
|
||||
return LibArbitrumL1.crossChainSender(_bridge);
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.8.0) (crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import "../CrossChainEnabled.sol";
|
||||
import "./LibArbitrumL2.sol";
|
||||
|
||||
/**
|
||||
* @dev https://arbitrum.io/[Arbitrum] specialization or the
|
||||
* {CrossChainEnabled} abstraction the L2 side (arbitrum).
|
||||
*
|
||||
* This version should only be deployed on L2 to process cross-chain messages
|
||||
* originating from L1. For the other side, use {CrossChainEnabledArbitrumL1}.
|
||||
*
|
||||
* Arbitrum L2 includes the `ArbSys` contract at a fixed address. Therefore,
|
||||
* this specialization of {CrossChainEnabled} does not include a constructor.
|
||||
*
|
||||
* _Available since v4.6._
|
||||
*
|
||||
* WARNING: There is currently a bug in Arbitrum that causes this contract to
|
||||
* fail to detect cross-chain calls when deployed behind a proxy. This will be
|
||||
* fixed when the network is upgraded to Arbitrum Nitro, currently scheduled for
|
||||
* August 31st 2022.
|
||||
*/
|
||||
abstract contract CrossChainEnabledArbitrumL2 is CrossChainEnabled {
|
||||
/**
|
||||
* @dev see {CrossChainEnabled-_isCrossChain}
|
||||
*/
|
||||
function _isCrossChain() internal view virtual override returns (bool) {
|
||||
return LibArbitrumL2.isCrossChain(LibArbitrumL2.ARBSYS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev see {CrossChainEnabled-_crossChainSender}
|
||||
*/
|
||||
function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
|
||||
return LibArbitrumL2.crossChainSender(LibArbitrumL2.ARBSYS);
|
||||
}
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.8.0) (crosschain/arbitrum/LibArbitrumL1.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import {IBridge as ArbitrumL1_Bridge} from "../../vendor/arbitrum/IBridge.sol";
|
||||
import {IOutbox as ArbitrumL1_Outbox} from "../../vendor/arbitrum/IOutbox.sol";
|
||||
import "../errors.sol";
|
||||
|
||||
/**
|
||||
* @dev Primitives for cross-chain aware contracts for
|
||||
* https://arbitrum.io/[Arbitrum].
|
||||
*
|
||||
* This version should only be used on L1 to process cross-chain messages
|
||||
* originating from L2. For the other side, use {LibArbitrumL2}.
|
||||
*/
|
||||
library LibArbitrumL1 {
|
||||
/**
|
||||
* @dev Returns whether the current function call is the result of a
|
||||
* cross-chain message relayed by the `bridge`.
|
||||
*/
|
||||
function isCrossChain(address bridge) internal view returns (bool) {
|
||||
return msg.sender == bridge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the address of the sender that triggered the current
|
||||
* cross-chain message through the `bridge`.
|
||||
*
|
||||
* NOTE: {isCrossChain} should be checked before trying to recover the
|
||||
* sender, as it will revert with `NotCrossChainCall` if the current
|
||||
* function call is not the result of a cross-chain message.
|
||||
*/
|
||||
function crossChainSender(address bridge) internal view returns (address) {
|
||||
if (!isCrossChain(bridge)) revert NotCrossChainCall();
|
||||
|
||||
address sender = ArbitrumL1_Outbox(ArbitrumL1_Bridge(bridge).activeOutbox()).l2ToL1Sender();
|
||||
require(sender != address(0), "LibArbitrumL1: system messages without sender");
|
||||
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.8.0) (crosschain/arbitrum/LibArbitrumL2.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import {IArbSys as ArbitrumL2_Bridge} from "../../vendor/arbitrum/IArbSys.sol";
|
||||
import "../errors.sol";
|
||||
|
||||
/**
|
||||
* @dev Primitives for cross-chain aware contracts for
|
||||
* https://arbitrum.io/[Arbitrum].
|
||||
*
|
||||
* This version should only be used on L2 to process cross-chain messages
|
||||
* originating from L1. For the other side, use {LibArbitrumL1}.
|
||||
*
|
||||
* WARNING: There is currently a bug in Arbitrum that causes this contract to
|
||||
* fail to detect cross-chain calls when deployed behind a proxy. This will be
|
||||
* fixed when the network is upgraded to Arbitrum Nitro, currently scheduled for
|
||||
* August 31st 2022.
|
||||
*/
|
||||
library LibArbitrumL2 {
|
||||
/**
|
||||
* @dev Returns whether the current function call is the result of a
|
||||
* cross-chain message relayed by `arbsys`.
|
||||
*/
|
||||
address public constant ARBSYS = 0x0000000000000000000000000000000000000064;
|
||||
|
||||
function isCrossChain(address arbsys) internal view returns (bool) {
|
||||
return ArbitrumL2_Bridge(arbsys).wasMyCallersAddressAliased();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the address of the sender that triggered the current
|
||||
* cross-chain message through `arbsys`.
|
||||
*
|
||||
* NOTE: {isCrossChain} should be checked before trying to recover the
|
||||
* sender, as it will revert with `NotCrossChainCall` if the current
|
||||
* function call is not the result of a cross-chain message.
|
||||
*/
|
||||
function crossChainSender(address arbsys) internal view returns (address) {
|
||||
if (!isCrossChain(arbsys)) revert NotCrossChainCall();
|
||||
|
||||
return ArbitrumL2_Bridge(arbsys).myCallersAddressWithoutAliasing();
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/errors.sol)
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
error NotCrossChainCall();
|
||||
error InvalidCrossChainSender(address actual, address expected);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user