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:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
- next-v*
|
||||||
- release-v*
|
- release-v*
|
||||||
pull_request: {}
|
pull_request: {}
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
@ -107,7 +108,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Run CodeSpell
|
- name: Run CodeSpell
|
||||||
uses: codespell-project/actions-codespell@v1.0
|
uses: codespell-project/actions-codespell@v2.0
|
||||||
with:
|
with:
|
||||||
|
check_hidden: true
|
||||||
check_filenames: true
|
check_filenames: true
|
||||||
skip: package-lock.json,*.pdf
|
skip: package-lock.json,*.pdf
|
||||||
|
|||||||
81
CHANGELOG.md
81
CHANGELOG.md
@ -1,5 +1,86 @@
|
|||||||
# Changelog
|
# 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
|
### 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`.
|
- `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">
|
# <img src="logo.svg" alt="OpenZeppelin" height="40px">
|
||||||
|
|
||||||
[](https://www.npmjs.org/package/@openzeppelin/contracts)
|
[](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:
|
Once installed, you can use the contracts in the library by importing them:
|
||||||
|
|
||||||
```solidity
|
```solidity
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/access/AccessControlDefaultAdminRules.sol";
|
import "../patched/access/AccessControlDefaultAdminRules.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/access/AccessControl.sol";
|
import "../patched/access/AccessControl.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/utils/structs/DoubleEndedQueue.sol";
|
import "../patched/utils/structs/DoubleEndedQueue.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/token/ERC20/ERC20.sol";
|
import "../patched/token/ERC20/ERC20.sol";
|
||||||
import "../patched/token/ERC20/extensions/ERC20Permit.sol";
|
import "../patched/token/ERC20/extensions/ERC20Permit.sol";
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/token/ERC20/extensions/ERC20Permit.sol";
|
import "../patched/token/ERC20/extensions/ERC20Permit.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/token/ERC20/extensions/ERC20Wrapper.sol";
|
import "../patched/token/ERC20/extensions/ERC20Wrapper.sol";
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import "../patched/interfaces/IERC3156FlashBorrower.sol";
|
import "../patched/interfaces/IERC3156FlashBorrower.sol";
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
contract ERC3156FlashBorrowerHarness is IERC3156FlashBorrower {
|
contract ERC3156FlashBorrowerHarness is IERC3156FlashBorrower {
|
||||||
bytes32 somethingToReturn;
|
bytes32 somethingToReturn;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/token/ERC721/ERC721.sol";
|
import "../patched/token/ERC721/ERC721.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/interfaces/IERC721Receiver.sol";
|
import "../patched/interfaces/IERC721Receiver.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/utils/structs/EnumerableMap.sol";
|
import "../patched/utils/structs/EnumerableMap.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/utils/structs/EnumerableSet.sol";
|
import "../patched/utils/structs/EnumerableSet.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
pragma solidity ^0.8.2;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/proxy/utils/Initializable.sol";
|
import "../patched/proxy/utils/Initializable.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/access/Ownable2Step.sol";
|
import "../patched/access/Ownable2Step.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/access/Ownable.sol";
|
import "../patched/access/Ownable.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/security/Pausable.sol";
|
import "../patched/security/Pausable.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "../patched/governance/TimelockController.sol";
|
import "../patched/governance/TimelockController.sol";
|
||||||
|
|
||||||
|
|||||||
@ -12,44 +12,23 @@ use rule onlyGrantCanGrant filtered {
|
|||||||
│ Helpers │
|
│ Helpers │
|
||||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
*/
|
*/
|
||||||
|
definition timeSanity(env e) returns bool =
|
||||||
|
e.block.timestamp > 0 && e.block.timestamp + defaultAdminDelay(e) < max_uint48();
|
||||||
|
|
||||||
function max_uint48() returns mathint {
|
definition delayChangeWaitSanity(env e, uint48 newDelay) returns bool =
|
||||||
return (1 << 48) - 1;
|
e.block.timestamp + delayChangeWait_(e, newDelay) < max_uint48();
|
||||||
}
|
|
||||||
|
|
||||||
function nonZeroAccount(address account) returns bool {
|
definition isSet(uint48 schedule) returns bool =
|
||||||
return account != 0;
|
schedule != 0;
|
||||||
}
|
|
||||||
|
|
||||||
function timeSanity(env e) returns bool {
|
definition hasPassed(env e, uint48 schedule) returns bool =
|
||||||
return
|
schedule < e.block.timestamp;
|
||||||
e.block.timestamp > 0 && // Avoids 0 schedules
|
|
||||||
e.block.timestamp + defaultAdminDelay(e) < max_uint48();
|
|
||||||
}
|
|
||||||
|
|
||||||
function delayChangeWaitSanity(env e, uint48 newDelay) returns bool {
|
definition increasingDelaySchedule(env e, uint48 newDelay) returns mathint =
|
||||||
return e.block.timestamp + delayChangeWait_(e, newDelay) < max_uint48();
|
e.block.timestamp + min(newDelay, defaultAdminDelayIncreaseWait());
|
||||||
}
|
|
||||||
|
|
||||||
function isSet(uint48 schedule) returns bool {
|
definition decreasingDelaySchedule(env e, uint48 newDelay) returns mathint =
|
||||||
return schedule != 0;
|
e.block.timestamp + defaultAdminDelay(e) - newDelay;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
@ -57,11 +36,10 @@ function decreasingDelaySchedule(env e, uint48 newDelay) returns mathint {
|
|||||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
*/
|
*/
|
||||||
invariant defaultAdminConsistency(address account)
|
invariant defaultAdminConsistency(address account)
|
||||||
defaultAdmin() == account <=> hasRole(DEFAULT_ADMIN_ROLE(), account)
|
(account == defaultAdmin() && account != 0) <=> hasRole(DEFAULT_ADMIN_ROLE(), account)
|
||||||
{
|
{
|
||||||
preserved {
|
preserved with (env e) {
|
||||||
// defaultAdmin() returns the zero address when there's no default admin
|
require nonzerosender(e);
|
||||||
require nonZeroAccount(account);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,10 +50,12 @@ invariant defaultAdminConsistency(address account)
|
|||||||
*/
|
*/
|
||||||
invariant singleDefaultAdmin(address account, address another)
|
invariant singleDefaultAdmin(address account, address another)
|
||||||
hasRole(DEFAULT_ADMIN_ROLE(), account) && hasRole(DEFAULT_ADMIN_ROLE(), another) => another == account
|
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
|
preserved {
|
||||||
// triggering the transfer, which is known to be impossible by definition.
|
requireInvariant defaultAdminConsistency(account);
|
||||||
filtered { f -> f.selector != acceptDefaultAdminTransfer().selector }
|
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";
|
"roles can only be revoked by their owner except for the default admin role";
|
||||||
|
|
||||||
// effect
|
// effect
|
||||||
assert success => !hasRole(role, account), "role is revoked";
|
assert success => !hasRole(role, account),
|
||||||
|
"role is revoked";
|
||||||
|
|
||||||
// no side effect
|
// no side effect
|
||||||
assert hasOtherRoleBefore != hasOtherRoleAfter => (role == otherRole && account == otherAccount),
|
assert hasOtherRoleBefore != hasOtherRoleAfter => (role == otherRole && account == otherAccount),
|
||||||
@ -137,35 +118,59 @@ rule renounceRoleEffect(env e, bytes32 role) {
|
|||||||
address account;
|
address account;
|
||||||
address otherAccount;
|
address otherAccount;
|
||||||
|
|
||||||
bool hasOtherRoleBefore = hasRole(otherRole, otherAccount);
|
bool hasOtherRoleBefore = hasRole(otherRole, otherAccount);
|
||||||
uint48 scheduleBefore = pendingDefaultAdminSchedule_();
|
address adminBefore = defaultAdmin();
|
||||||
address pendingAdminBefore = pendingDefaultAdmin_();
|
address pendingAdminBefore = pendingDefaultAdmin_();
|
||||||
|
uint48 scheduleBefore = pendingDefaultAdminSchedule_();
|
||||||
|
|
||||||
renounceRole@withrevert(e, role, account);
|
renounceRole@withrevert(e, role, account);
|
||||||
bool success = !lastReverted;
|
bool success = !lastReverted;
|
||||||
|
|
||||||
bool hasOtherRoleAfter = hasRole(otherRole, otherAccount);
|
bool hasOtherRoleAfter = hasRole(otherRole, otherAccount);
|
||||||
|
address adminAfter = defaultAdmin();
|
||||||
|
address pendingAdminAfter = pendingDefaultAdmin_();
|
||||||
|
uint48 scheduleAfter = pendingDefaultAdminSchedule_();
|
||||||
|
|
||||||
// liveness
|
// liveness
|
||||||
assert success <=> (
|
assert success <=> (
|
||||||
account == e.msg.sender &&
|
account == e.msg.sender &&
|
||||||
(
|
(
|
||||||
|
role != DEFAULT_ADMIN_ROLE() ||
|
||||||
|
account != adminBefore ||
|
||||||
(
|
(
|
||||||
role != DEFAULT_ADMIN_ROLE()
|
|
||||||
) || (
|
|
||||||
role == DEFAULT_ADMIN_ROLE() &&
|
|
||||||
pendingAdminBefore == 0 &&
|
pendingAdminBefore == 0 &&
|
||||||
isSet(scheduleBefore) &&
|
isSet(scheduleBefore) &&
|
||||||
hasPassed(e, 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
|
// 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
|
// no side effect
|
||||||
assert hasOtherRoleBefore != hasOtherRoleAfter => (role == otherRole && account == otherAccount),
|
assert hasOtherRoleBefore != hasOtherRoleAfter => (
|
||||||
|
role == otherRole &&
|
||||||
|
account == otherAccount
|
||||||
|
),
|
||||||
"no other role is affected";
|
"no other role is affected";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,10 +180,6 @@ rule renounceRoleEffect(env e, bytes32 role) {
|
|||||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
*/
|
*/
|
||||||
rule noDefaultAdminChange(env e, method f, calldataarg args) {
|
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();
|
address adminBefore = defaultAdmin();
|
||||||
f(e, args);
|
f(e, args);
|
||||||
address adminAfter = defaultAdmin();
|
address adminAfter = defaultAdmin();
|
||||||
@ -186,18 +187,17 @@ rule noDefaultAdminChange(env e, method f, calldataarg args) {
|
|||||||
assert adminBefore != adminAfter => (
|
assert adminBefore != adminAfter => (
|
||||||
f.selector == acceptDefaultAdminTransfer().selector ||
|
f.selector == acceptDefaultAdminTransfer().selector ||
|
||||||
f.selector == renounceRole(bytes32,address).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) {
|
rule noPendingDefaultAdminChange(env e, method f, calldataarg args) {
|
||||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
|
||||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
|
||||||
|
|
||||||
address pendingAdminBefore = pendingDefaultAdmin_();
|
address pendingAdminBefore = pendingDefaultAdmin_();
|
||||||
address scheduleBefore = pendingDefaultAdminSchedule_();
|
address scheduleBefore = pendingDefaultAdminSchedule_();
|
||||||
f(e, args);
|
f(e, args);
|
||||||
@ -210,8 +210,10 @@ rule noPendingDefaultAdminChange(env e, method f, calldataarg args) {
|
|||||||
) => (
|
) => (
|
||||||
f.selector == beginDefaultAdminTransfer(address).selector ||
|
f.selector == beginDefaultAdminTransfer(address).selector ||
|
||||||
f.selector == acceptDefaultAdminTransfer().selector ||
|
f.selector == acceptDefaultAdminTransfer().selector ||
|
||||||
f.selector == cancelDefaultAdminTransfer().selector
|
f.selector == cancelDefaultAdminTransfer().selector ||
|
||||||
), "pending admin and its schedule is only affected by beginning, accepting or cancelling an admin transfer";
|
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);
|
f(e, args);
|
||||||
uint48 delayAfter = defaultAdminDelay(e);
|
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 => (
|
assert pendingDelayBefore != pendingDelayAfter => (
|
||||||
f.selector == changeDefaultAdminDelay(uint48).selector ||
|
f.selector == changeDefaultAdminDelay(uint48).selector ||
|
||||||
f.selector == rollbackDefaultAdminDelay().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) {
|
rule beginDefaultAdminTransfer(env e, address newAdmin) {
|
||||||
require nonpayable(e);
|
|
||||||
require timeSanity(e);
|
require timeSanity(e);
|
||||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
require nonpayable(e);
|
||||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
require nonzerosender(e);
|
||||||
|
requireInvariant defaultAdminConsistency(e.msg.sender);
|
||||||
|
|
||||||
beginDefaultAdminTransfer@withrevert(e, newAdmin);
|
beginDefaultAdminTransfer@withrevert(e, newAdmin);
|
||||||
bool success = !lastReverted;
|
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) {
|
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);
|
uint48 delayBefore = defaultAdminDelay(e1);
|
||||||
address adminBefore = defaultAdmin();
|
address adminBefore = defaultAdmin();
|
||||||
|
|
||||||
// There might be a better way to generalize this without requiring `beginDefaultAdminTransfer`, but currently
|
// 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.
|
// it's the only way in which we can attest that only `delayBefore` has passed before a change.
|
||||||
beginDefaultAdminTransfer(e1, newAdmin);
|
beginDefaultAdminTransfer(e1, newAdmin);
|
||||||
f(e2, args);
|
f(e2, args);
|
||||||
|
|
||||||
address adminAfter = defaultAdmin();
|
address adminAfter = defaultAdmin();
|
||||||
|
|
||||||
assert adminAfter == newAdmin => ((e2.block.timestamp >= e1.block.timestamp + delayBefore) || adminBefore == newAdmin),
|
// change can only happen towards the newAdmin, with the delay
|
||||||
"A delay can't change in less than applied schedule";
|
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) {
|
rule acceptDefaultAdminTransfer(env e) {
|
||||||
require nonpayable(e);
|
require nonpayable(e);
|
||||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
|
||||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
|
||||||
|
|
||||||
address pendingAdminBefore = pendingDefaultAdmin_();
|
address pendingAdminBefore = pendingDefaultAdmin_();
|
||||||
uint48 scheduleAfter = pendingDefaultAdminSchedule_();
|
uint48 scheduleBefore = pendingDefaultAdminSchedule_();
|
||||||
|
|
||||||
acceptDefaultAdminTransfer@withrevert(e);
|
acceptDefaultAdminTransfer@withrevert(e);
|
||||||
bool success = !lastReverted;
|
bool success = !lastReverted;
|
||||||
|
|
||||||
// liveness
|
// 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";
|
"only the pending default admin can accept the role after the schedule has been set and passed";
|
||||||
|
|
||||||
// effect
|
// effect
|
||||||
@ -338,8 +350,8 @@ rule acceptDefaultAdminTransfer(env e) {
|
|||||||
*/
|
*/
|
||||||
rule cancelDefaultAdminTransfer(env e) {
|
rule cancelDefaultAdminTransfer(env e) {
|
||||||
require nonpayable(e);
|
require nonpayable(e);
|
||||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
require nonzerosender(e);
|
||||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
requireInvariant defaultAdminConsistency(e.msg.sender);
|
||||||
|
|
||||||
cancelDefaultAdminTransfer@withrevert(e);
|
cancelDefaultAdminTransfer@withrevert(e);
|
||||||
bool success = !lastReverted;
|
bool success = !lastReverted;
|
||||||
@ -361,11 +373,11 @@ rule cancelDefaultAdminTransfer(env e) {
|
|||||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
*/
|
*/
|
||||||
rule changeDefaultAdminDelay(env e, uint48 newDelay) {
|
rule changeDefaultAdminDelay(env e, uint48 newDelay) {
|
||||||
require nonpayable(e);
|
|
||||||
require timeSanity(e);
|
require timeSanity(e);
|
||||||
|
require nonpayable(e);
|
||||||
|
require nonzerosender(e);
|
||||||
require delayChangeWaitSanity(e, newDelay);
|
require delayChangeWaitSanity(e, newDelay);
|
||||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
requireInvariant defaultAdminConsistency(e.msg.sender);
|
||||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
|
||||||
|
|
||||||
uint48 delayBefore = defaultAdminDelay(e);
|
uint48 delayBefore = defaultAdminDelay(e);
|
||||||
|
|
||||||
@ -377,7 +389,9 @@ rule changeDefaultAdminDelay(env e, uint48 newDelay) {
|
|||||||
"only the current default admin can begin a delay change";
|
"only the current default admin can begin a delay change";
|
||||||
|
|
||||||
// effect
|
// effect
|
||||||
assert success => pendingDelay_(e) == newDelay, "pending delay is set";
|
assert success => pendingDelay_(e) == newDelay,
|
||||||
|
"pending delay is set";
|
||||||
|
|
||||||
assert success => (
|
assert success => (
|
||||||
pendingDelaySchedule_(e) > e.block.timestamp ||
|
pendingDelaySchedule_(e) > e.block.timestamp ||
|
||||||
delayBefore == newDelay || // Interpreted as decreasing, x - x = 0
|
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) {
|
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);
|
uint48 delayBefore = defaultAdminDelay(e1);
|
||||||
|
|
||||||
changeDefaultAdminDelay(e1, newDelay);
|
changeDefaultAdminDelay(e1, newDelay);
|
||||||
f(e2, args);
|
f(e2, args);
|
||||||
|
|
||||||
uint48 delayAfter = defaultAdminDelay(e2);
|
uint48 delayAfter = defaultAdminDelay(e2);
|
||||||
|
|
||||||
mathint delayWait = newDelay > delayBefore ? increasingDelaySchedule(e1, newDelay) : decreasingDelaySchedule(e1, newDelay);
|
mathint delayWait = newDelay > delayBefore ? increasingDelaySchedule(e1, newDelay) : decreasingDelaySchedule(e1, newDelay);
|
||||||
|
|
||||||
assert delayAfter == newDelay => (e2.block.timestamp >= delayWait || delayBefore == newDelay),
|
assert delayAfter != delayBefore => (
|
||||||
"A delay can't change in less than applied schedule";
|
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) {
|
rule rollbackDefaultAdminDelay(env e) {
|
||||||
require nonpayable(e);
|
require nonpayable(e);
|
||||||
requireInvariant defaultAdminConsistency(defaultAdmin());
|
require nonzerosender(e);
|
||||||
requireInvariant singleDefaultAdmin(e.msg.sender, defaultAdmin());
|
requireInvariant defaultAdminConsistency(e.msg.sender);
|
||||||
|
|
||||||
rollbackDefaultAdminDelay@withrevert(e);
|
rollbackDefaultAdminDelay@withrevert(e);
|
||||||
bool success = !lastReverted;
|
bool success = !lastReverted;
|
||||||
@ -443,58 +462,3 @@ rule rollbackDefaultAdminDelay(env e) {
|
|||||||
assert success => pendingDelaySchedule_(e) == 0,
|
assert success => pendingDelaySchedule_(e) == 0,
|
||||||
"Pending default admin delay is reset";
|
"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 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
|
// 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 "./IAccessControl.sol";
|
||||||
import "../utils/Context.sol";
|
import "../utils/Context.sol";
|
||||||
@ -183,30 +183,6 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
|
|||||||
_revokeRole(role, account);
|
_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.
|
* @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
|
// 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 "./AccessControl.sol";
|
||||||
import "./IAccessControlDefaultAdminRules.sol";
|
import "./IAccessControlDefaultAdminRules.sol";
|
||||||
@ -106,12 +106,13 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
|
|||||||
* non-administrated role.
|
* non-administrated role.
|
||||||
*/
|
*/
|
||||||
function renounceRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {
|
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();
|
(address newDefaultAdmin, uint48 schedule) = pendingDefaultAdmin();
|
||||||
require(
|
require(
|
||||||
newDefaultAdmin == address(0) && _isScheduleSet(schedule) && _hasSchedulePassed(schedule),
|
newDefaultAdmin == address(0) && _isScheduleSet(schedule) && _hasSchedulePassed(schedule),
|
||||||
"AccessControl: only can renounce in two delayed steps"
|
"AccessControl: only can renounce in two delayed steps"
|
||||||
);
|
);
|
||||||
|
delete _pendingDefaultAdminSchedule;
|
||||||
}
|
}
|
||||||
super.renounceRole(role, account);
|
super.renounceRole(role, account);
|
||||||
}
|
}
|
||||||
@ -137,7 +138,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
|
|||||||
* @dev See {AccessControl-_revokeRole}.
|
* @dev See {AccessControl-_revokeRole}.
|
||||||
*/
|
*/
|
||||||
function _revokeRole(bytes32 role, address account) internal virtual override {
|
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;
|
delete _currentDefaultAdmin;
|
||||||
}
|
}
|
||||||
super._revokeRole(role, account);
|
super._revokeRole(role, account);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)
|
// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "./IAccessControlEnumerable.sol";
|
import "./IAccessControlEnumerable.sol";
|
||||||
import "./AccessControl.sol";
|
import "./AccessControl.sol";
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
|
// 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.
|
* @dev External interface of AccessControl declared to support ERC165 detection.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// 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";
|
import "./IAccessControl.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
|
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
|
||||||
|
|
||||||
pragma solidity ^0.8.0;
|
pragma solidity ^0.8.19;
|
||||||
|
|
||||||
import "./IAccessControl.sol";
|
import "./IAccessControl.sol";
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// 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";
|
import "../utils/Context.sol";
|
||||||
|
|
||||||
@ -25,8 +25,8 @@ abstract contract Ownable is Context {
|
|||||||
/**
|
/**
|
||||||
* @dev Initializes the contract setting the deployer as the initial owner.
|
* @dev Initializes the contract setting the deployer as the initial owner.
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor(address initialOwner) {
|
||||||
_transferOwnership(_msgSender());
|
_transferOwnership(initialOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// 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";
|
import "./Ownable.sol";
|
||||||
|
|
||||||
|
|||||||
@ -18,8 +18,6 @@ This directory provides ways to restrict who can access the functions of a contr
|
|||||||
|
|
||||||
{{AccessControl}}
|
{{AccessControl}}
|
||||||
|
|
||||||
{{AccessControlCrossChain}}
|
|
||||||
|
|
||||||
{{IAccessControlEnumerable}}
|
{{IAccessControlEnumerable}}
|
||||||
|
|
||||||
{{AccessControlEnumerable}}
|
{{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