Remove code in preparation for v5.0 (#4258)

Co-authored-by: Ernesto García <ernestognw@gmail.com>
Co-authored-by: Francisco <fg@frang.io>
pull/4260/head^2
Hadrien Croubois 2 years ago committed by GitHub
parent 8de6eba8a3
commit 0f10efe232
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      .changeset/beige-ducks-flow.md
  2. 5
      .changeset/fluffy-gifts-build.md
  3. 5
      .changeset/friendly-suits-camp.md
  4. 5
      .changeset/selfish-queens-rest.md
  5. 5
      .changeset/spicy-ducks-cough.md
  6. 5
      .changeset/swift-berries-sort.md
  7. 5
      .changeset/tame-geckos-search.md
  8. 5
      .changeset/three-weeks-double.md
  9. 24
      contracts/access/AccessControl.sol
  10. 45
      contracts/access/AccessControlCrossChain.sol
  11. 2
      contracts/access/README.adoc
  12. 54
      contracts/crosschain/CrossChainEnabled.sol
  13. 34
      contracts/crosschain/README.adoc
  14. 49
      contracts/crosschain/amb/CrossChainEnabledAMB.sol
  15. 35
      contracts/crosschain/amb/LibAMB.sol
  16. 44
      contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol
  17. 40
      contracts/crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol
  18. 42
      contracts/crosschain/arbitrum/LibArbitrumL1.sol
  19. 45
      contracts/crosschain/arbitrum/LibArbitrumL2.sol
  20. 7
      contracts/crosschain/errors.sol
  21. 41
      contracts/crosschain/optimism/CrossChainEnabledOptimism.sol
  22. 36
      contracts/crosschain/optimism/LibOptimism.sol
  23. 72
      contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol
  24. 4
      contracts/governance/README.adoc
  25. 6
      contracts/governance/TimelockController.sol
  26. 11
      contracts/governance/compatibility/GovernorCompatibilityBravo.sol
  27. 23
      contracts/governance/extensions/GovernorProposalThreshold.sol
  28. 16
      contracts/governance/extensions/GovernorVotesQuorumFraction.sol
  29. 18
      contracts/interfaces/IERC1820Implementer.sol
  30. 110
      contracts/interfaces/IERC1820Registry.sol
  31. 197
      contracts/interfaces/IERC777.sol
  32. 32
      contracts/interfaces/IERC777Recipient.sol
  33. 32
      contracts/interfaces/IERC777Sender.sol
  34. 7
      contracts/interfaces/draft-IERC2612.sol
  35. 8
      contracts/mocks/AccessControlCrossChainMock.sol
  36. 18
      contracts/mocks/ConditionalEscrowMock.sol
  37. 15
      contracts/mocks/PullPaymentMock.sol
  38. 72
      contracts/mocks/SafeMathMemoryCheck.sol
  39. 39
      contracts/mocks/TimersBlockNumberImpl.sol
  40. 39
      contracts/mocks/TimersTimestampImpl.sol
  41. 94
      contracts/mocks/crosschain/bridges.sol
  42. 54
      contracts/mocks/crosschain/receivers.sol
  43. 17
      contracts/mocks/governance/GovernorMock.sol
  44. 2
      contracts/mocks/token/ERC20PermitNoRevertMock.sol
  45. 2
      contracts/mocks/token/ERC721ConsecutiveMock.sol
  46. 13
      contracts/mocks/token/ERC777Mock.sol
  47. 152
      contracts/mocks/token/ERC777SenderRecipientMock.sol
  48. 79
      contracts/mocks/wizard/MyGovernor1.sol
  49. 85
      contracts/mocks/wizard/MyGovernor2.sol
  50. 94
      contracts/mocks/wizard/MyGovernor3.sol
  51. 21
      contracts/proxy/beacon/BeaconProxy.sol
  52. 27
      contracts/proxy/transparent/TransparentUpgradeableProxy.sol
  53. 74
      contracts/security/PullPayment.sol
  54. 3
      contracts/security/README.adoc
  55. 8
      contracts/token/ERC20/extensions/ERC20Permit.sol
  56. 8
      contracts/token/ERC20/extensions/draft-ERC20Permit.sol
  57. 7
      contracts/token/ERC20/extensions/draft-IERC20Permit.sol
  58. 18
      contracts/token/ERC20/utils/SafeERC20.sol
  59. 9
      contracts/token/ERC721/extensions/draft-ERC721Votes.sol
  60. 517
      contracts/token/ERC777/ERC777.sol
  61. 200
      contracts/token/ERC777/IERC777.sol
  62. 35
      contracts/token/ERC777/IERC777Recipient.sol
  63. 35
      contracts/token/ERC777/IERC777Sender.sol
  64. 26
      contracts/token/ERC777/README.adoc
  65. 196
      contracts/utils/Checkpoints.sol
  66. 25
      contracts/utils/README.adoc
  67. 75
      contracts/utils/Timers.sol
  68. 3
      contracts/utils/cryptography/ECDSA.sol
  69. 8
      contracts/utils/cryptography/draft-EIP712.sol
  70. 25
      contracts/utils/escrow/ConditionalEscrow.sol
  71. 67
      contracts/utils/escrow/Escrow.sol
  72. 100
      contracts/utils/escrow/RefundEscrow.sol
  73. 43
      contracts/utils/introspection/ERC1820Implementer.sol
  74. 20
      contracts/utils/introspection/IERC1820Implementer.sol
  75. 112
      contracts/utils/introspection/IERC1820Registry.sol
  76. 66
      contracts/utils/math/Math.sol
  77. 3
      contracts/utils/math/SafeCast.sol
  78. 215
      contracts/utils/math/SafeMath.sol
  79. 68
      contracts/utils/math/SignedSafeMath.sol
  80. 68
      contracts/utils/structs/EnumerableMap.sol
  81. 41
      contracts/vendor/amb/IAMB.sol
  82. 134
      contracts/vendor/arbitrum/IArbSys.sol
  83. 102
      contracts/vendor/arbitrum/IBridge.sol
  84. 16
      contracts/vendor/arbitrum/IDelayedMessageProvider.sol
  85. 152
      contracts/vendor/arbitrum/IInbox.sol
  86. 117
      contracts/vendor/arbitrum/IOutbox.sol
  87. 34
      contracts/vendor/optimism/ICrossDomainMessenger.sol
  88. 22
      contracts/vendor/optimism/LICENSE
  89. 7
      contracts/vendor/polygon/IFxMessageProcessor.sol
  90. 3
      docs/modules/ROOT/nav.adoc
  91. 210
      docs/modules/ROOT/pages/crosschain.adoc
  92. 8
      docs/modules/ROOT/pages/erc1155.adoc
  93. 75
      docs/modules/ROOT/pages/erc777.adoc
  94. 1
      docs/modules/ROOT/pages/tokens.adoc
  95. 10
      docs/modules/ROOT/pages/utilities.adoc
  96. 6
      hardhat.config.js
  97. 86
      scripts/generate/templates/Checkpoints.js
  98. 7
      scripts/generate/templates/Checkpoints.opts.js
  99. 118
      scripts/generate/templates/Checkpoints.t.js
  100. 30
      scripts/generate/templates/EnumerableMap.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---
Remove deprecated GovernorProposalThreshold module.

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---
Remove ERC1820Implementer.

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---
Remove Checkpoints.History.

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---
Remove PullPayment and Escrow contracts (Escrow, ConditionalEscrow, RefundEscrow).

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---
Remove the Timers library.

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---
Remove ERC777 implementation.

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---
Remove SafeMath and SignedSafeMath libraries.

@ -0,0 +1,5 @@
---
'openzeppelin-solidity': major
---
Remove CrossChain contracts, including AccessControlCrossChain and all the vendored bridge interfaces.

@ -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;
}
}

@ -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);

@ -1,41 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/optimism/CrossChainEnabledOptimism.sol)
pragma solidity ^0.8.4;
import "../CrossChainEnabled.sol";
import "./LibOptimism.sol";
/**
* @dev https://www.optimism.io/[Optimism] specialization or the
* {CrossChainEnabled} abstraction.
*
* The messenger (`CrossDomainMessenger`) contract is provided and maintained by
* the optimism team. You can find the address of this contract on mainnet and
* kovan in the https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts/deployments[deployments section of Optimism monorepo].
*
* _Available since v4.6._
*/
abstract contract CrossChainEnabledOptimism is CrossChainEnabled {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable _messenger;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address messenger) {
_messenger = messenger;
}
/**
* @dev see {CrossChainEnabled-_isCrossChain}
*/
function _isCrossChain() internal view virtual override returns (bool) {
return LibOptimism.isCrossChain(_messenger);
}
/**
* @dev see {CrossChainEnabled-_crossChainSender}
*/
function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
return LibOptimism.crossChainSender(_messenger);
}
}

@ -1,36 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/optimism/LibOptimism.sol)
pragma solidity ^0.8.4;
import {ICrossDomainMessenger as Optimism_Bridge} from "../../vendor/optimism/ICrossDomainMessenger.sol";
import "../errors.sol";
/**
* @dev Primitives for cross-chain aware contracts for https://www.optimism.io/[Optimism].
* See the https://community.optimism.io/docs/developers/bridge/messaging/#accessing-msg-sender[documentation]
* for the functionality used here.
*/
library LibOptimism {
/**
* @dev Returns whether the current function call is the result of a
* cross-chain message relayed by `messenger`.
*/
function isCrossChain(address messenger) internal view returns (bool) {
return msg.sender == messenger;
}
/**
* @dev Returns the address of the sender that triggered the current
* cross-chain message through `messenger`.
*
* 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 messenger) internal view returns (address) {
if (!isCrossChain(messenger)) revert NotCrossChainCall();
return Optimism_Bridge(messenger).xDomainMessageSender();
}
}

@ -1,72 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/polygon/CrossChainEnabledPolygonChild.sol)
pragma solidity ^0.8.4;
import "../CrossChainEnabled.sol";
import "../../security/ReentrancyGuard.sol";
import "../../utils/Address.sol";
import "../../vendor/polygon/IFxMessageProcessor.sol";
address constant DEFAULT_SENDER = 0x000000000000000000000000000000000000dEaD;
/**
* @dev https://polygon.technology/[Polygon] specialization or the
* {CrossChainEnabled} abstraction the child side (polygon/mumbai).
*
* This version should only be deployed on child chain to process cross-chain
* messages originating from the parent chain.
*
* The fxChild contract is provided and maintained by the polygon team. You can
* find the address of this contract polygon and mumbai in
* https://docs.polygon.technology/docs/develop/l1-l2-communication/fx-portal/#contract-addresses[Polygon's Fx-Portal documentation].
*
* _Available since v4.6._
*/
abstract contract CrossChainEnabledPolygonChild is IFxMessageProcessor, CrossChainEnabled, ReentrancyGuard {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable _fxChild;
address private _sender = DEFAULT_SENDER;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address fxChild) {
_fxChild = fxChild;
}
/**
* @dev see {CrossChainEnabled-_isCrossChain}
*/
function _isCrossChain() internal view virtual override returns (bool) {
return msg.sender == _fxChild;
}
/**
* @dev see {CrossChainEnabled-_crossChainSender}
*/
function _crossChainSender() internal view virtual override onlyCrossChain returns (address) {
return _sender;
}
/**
* @dev External entry point to receive and relay messages originating
* from the fxChild.
*
* Non-reentrancy is crucial to avoid a cross-chain call being able
* to impersonate anyone by just looping through this with user-defined
* arguments.
*
* Note: if _fxChild calls any other function that does a delegate-call,
* then security could be compromised.
*/
function processMessageFromRoot(
uint256 /* stateId */,
address rootMessageSender,
bytes calldata data
) external override nonReentrant {
if (!_isCrossChain()) revert NotCrossChainCall();
_sender = rootMessageSender;
Address.functionDelegateCall(address(this), data, "cross-chain execution failed");
_sender = DEFAULT_SENDER;
}
}

@ -80,10 +80,6 @@ NOTE: Functions of the `Governor` contract do not include access control. If you
{{GovernorCompatibilityBravo}}
=== Deprecated
{{GovernorProposalThreshold}}
== Utils
{{Votes}}

@ -88,13 +88,13 @@ contract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver
// register proposers and cancellers
for (uint256 i = 0; i < proposers.length; ++i) {
_setupRole(PROPOSER_ROLE, proposers[i]);
_setupRole(CANCELLER_ROLE, proposers[i]);
_grantRole(PROPOSER_ROLE, proposers[i]);
_grantRole(CANCELLER_ROLE, proposers[i]);
}
// register executors
for (uint256 i = 0; i < executors.length; ++i) {
_setupRole(EXECUTOR_ROLE, executors[i]);
_grantRole(EXECUTOR_ROLE, executors[i]);
}
_minDelay = minDelay;

@ -26,7 +26,6 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
}
struct ProposalDetails {
address proposer;
address[] targets;
uint256[] values;
string[] signatures;
@ -56,7 +55,7 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
string memory description
) public virtual override(IGovernor, Governor) returns (uint256) {
// Stores the proposal details (if not already present) and executes the propose logic from the core.
_storeProposal(_msgSender(), targets, values, new string[](calldatas.length), calldatas, description);
_storeProposal(targets, values, new string[](calldatas.length), calldatas, description);
return super.propose(targets, values, calldatas, description);
}
@ -75,7 +74,7 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
// after the full proposal is stored, so the store operation included in the fallback will be skipped. Here we
// call `propose` and not `super.propose` to make sure if a child contract override `propose`, whatever code
// is added there is also executed when calling this alternative interface.
_storeProposal(_msgSender(), targets, values, signatures, calldatas, description);
_storeProposal(targets, values, signatures, calldatas, description);
return propose(targets, values, _encodeCalldata(signatures, calldatas), description);
}
@ -132,7 +131,7 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
bytes32 descriptionHash
) public virtual override(IGovernor, Governor) returns (uint256) {
uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
address proposer = _proposalDetails[proposalId].proposer;
address proposer = proposalProposer(proposalId);
require(
_msgSender() == proposer || getVotes(proposer, clock() - 1) < proposalThreshold(),
@ -182,7 +181,6 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
* @dev Store proposal metadata (if not already present) for later lookup.
*/
function _storeProposal(
address proposer,
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
@ -194,7 +192,6 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
ProposalDetails storage details = _proposalDetails[proposalId];
if (details.descriptionHash == bytes32(0)) {
details.proposer = proposer;
details.targets = targets;
details.values = values;
details.signatures = signatures;
@ -228,12 +225,12 @@ abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorComp
)
{
id = proposalId;
proposer = proposalProposer(proposalId);
eta = proposalEta(proposalId);
startBlock = proposalSnapshot(proposalId);
endBlock = proposalDeadline(proposalId);
ProposalDetails storage details = _proposalDetails[proposalId];
proposer = details.proposer;
forVotes = details.forVotes;
againstVotes = details.againstVotes;
abstainVotes = details.abstainVotes;

@ -1,23 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (governance/extensions/GovernorProposalThreshold.sol)
pragma solidity ^0.8.0;
import "../Governor.sol";
/**
* @dev Extension of {Governor} for proposal restriction to token holders with a minimum balance.
*
* _Available since v4.3._
* _Deprecated since v4.4._
*/
abstract contract GovernorProposalThreshold is Governor {
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public virtual override returns (uint256) {
return super.propose(targets, values, calldatas, description);
}
}

@ -16,8 +16,6 @@ import "../../utils/math/SafeCast.sol";
abstract contract GovernorVotesQuorumFraction is GovernorVotes {
using Checkpoints for Checkpoints.Trace224;
uint256 private _quorumNumerator; // DEPRECATED in favor of _quorumNumeratorHistory
/// @custom:oz-retyped-from Checkpoints.History
Checkpoints.Trace224 private _quorumNumeratorHistory;
@ -38,7 +36,7 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
* @dev Returns the current quorum numerator. See {quorumDenominator}.
*/
function quorumNumerator() public view virtual returns (uint256) {
return _quorumNumeratorHistory._checkpoints.length == 0 ? _quorumNumerator : _quorumNumeratorHistory.latest();
return _quorumNumeratorHistory.latest();
}
/**
@ -47,9 +45,6 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
// If history is empty, fallback to old storage
uint256 length = _quorumNumeratorHistory._checkpoints.length;
if (length == 0) {
return _quorumNumerator;
}
// Optimistic search, check the latest checkpoint
Checkpoints.Checkpoint224 memory latest = _quorumNumeratorHistory._checkpoints[length - 1];
@ -105,15 +100,6 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
);
uint256 oldQuorumNumerator = quorumNumerator();
// Make sure we keep track of the original numerator in contracts upgraded from a version without checkpoints.
if (oldQuorumNumerator != 0 && _quorumNumeratorHistory._checkpoints.length == 0) {
_quorumNumeratorHistory._checkpoints.push(
Checkpoints.Checkpoint224({_key: 0, _value: SafeCast.toUint224(oldQuorumNumerator)})
);
}
// Set new quorum for future proposals
_quorumNumeratorHistory.push(SafeCast.toUint32(clock()), SafeCast.toUint224(newQuorumNumerator));
emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);

@ -1,6 +1,20 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1820Implementer.sol)
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC1820Implementer.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC1820Implementer.sol";
/**
* @dev Interface for an ERC1820 implementer, as defined in the
* https://eips.ethereum.org/EIPS/eip-1820#interface-implementation-erc1820implementerinterface[EIP].
* Used by contracts that will be registered as implementers in the
* {IERC1820Registry}.
*/
interface IERC1820Implementer {
/**
* @dev Returns a special value (`ERC1820_ACCEPT_MAGIC`) if this contract
* implements `interfaceHash` for `account`.
*
* See {IERC1820Registry-setInterfaceImplementer}.
*/
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32);
}

@ -1,6 +1,112 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1820Registry.sol)
// OpenZeppelin Contracts (last updated v4.8.0) (utils/introspection/IERC1820Registry.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC1820Registry.sol";
/**
* @dev Interface of the global ERC1820 Registry, as defined in the
* https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
* implementers for interfaces in this registry, as well as query support.
*
* Implementers may be shared by multiple accounts, and can also implement more
* than a single interface for each account. Contracts can implement interfaces
* for themselves, but externally-owned accounts (EOA) must delegate this to a
* contract.
*
* {IERC165} interfaces can also be queried via the registry.
*
* For an in-depth explanation and source code analysis, see the EIP text.
*/
interface IERC1820Registry {
event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
event ManagerChanged(address indexed account, address indexed newManager);
/**
* @dev Sets `newManager` as the manager for `account`. A manager of an
* account is able to set interface implementers for it.
*
* By default, each account is its own manager. Passing a value of `0x0` in
* `newManager` will reset the manager to this initial state.
*
* Emits a {ManagerChanged} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
*/
function setManager(address account, address newManager) external;
/**
* @dev Returns the manager for `account`.
*
* See {setManager}.
*/
function getManager(address account) external view returns (address);
/**
* @dev Sets the `implementer` contract as ``account``'s implementer for
* `interfaceHash`.
*
* `account` being the zero address is an alias for the caller's address.
* The zero address can also be used in `implementer` to remove an old one.
*
* See {interfaceHash} to learn how these are created.
*
* Emits an {InterfaceImplementerSet} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
* - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
* end in 28 zeroes).
* - `implementer` must implement {IERC1820Implementer} and return true when
* queried for support, unless `implementer` is the caller. See
* {IERC1820Implementer-canImplementInterfaceForAddress}.
*/
function setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer) external;
/**
* @dev Returns the implementer of `interfaceHash` for `account`. If no such
* implementer is registered, returns the zero address.
*
* If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
* zeroes), `account` will be queried for support of it.
*
* `account` being the zero address is an alias for the caller's address.
*/
function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);
/**
* @dev Returns the interface hash for an `interfaceName`, as defined in the
* corresponding
* https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
*/
function interfaceHash(string calldata interfaceName) external pure returns (bytes32);
/**
* @notice Updates the cache with whether the contract implements an ERC165 interface or not.
* @param account Address of the contract for which to update the cache.
* @param interfaceId ERC165 interface for which to update the cache.
*/
function updateERC165Cache(address account, bytes4 interfaceId) external;
/**
* @notice Checks whether a contract implements an ERC165 interface or not.
* If the result is not cached a direct lookup on the contract address is performed.
* If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
* {updateERC165Cache} with the contract address.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);
/**
* @notice Checks whether a contract implements an ERC165 interface or not without using or updating the cache.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
}

@ -1,6 +1,199 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777.sol)
pragma solidity ^0.8.0;
import "../token/ERC777/IERC777.sol";
/**
* @dev Interface of the ERC777Token standard as defined in the EIP.
*
* This contract uses the
* https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
* token holders and recipients react to token movements by using setting implementers
* for the associated interfaces in said registry. See {IERC1820Registry} and
* {IERC1820Implementer}.
*/
interface IERC777 {
/**
* @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`.
*
* Note that some additional user `data` and `operatorData` can be logged in the event.
*/
event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
/**
* @dev Emitted when `operator` destroys `amount` tokens from `account`.
*
* Note that some additional user `data` and `operatorData` can be logged in the event.
*/
event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
/**
* @dev Emitted when `operator` is made operator for `tokenHolder`.
*/
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
/**
* @dev Emitted when `operator` is revoked its operator status for `tokenHolder`.
*/
event RevokedOperator(address indexed operator, address indexed tokenHolder);
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the smallest part of the token that is not divisible. This
* means all token operations (creation, movement and destruction) must have
* amounts that are a multiple of this number.
*
* For most token contracts, this value will equal 1.
*/
function granularity() external view returns (uint256);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by an account (`owner`).
*/
function balanceOf(address owner) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* If send or receive hooks are registered for the caller and `recipient`,
* the corresponding functions will be called with `data` and empty
* `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
*
* Emits a {Sent} event.
*
* Requirements
*
* - the caller must have at least `amount` tokens.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function send(address recipient, uint256 amount, bytes calldata data) external;
/**
* @dev Destroys `amount` tokens from the caller's account, reducing the
* total supply.
*
* If a send hook is registered for the caller, the corresponding function
* will be called with `data` and empty `operatorData`. See {IERC777Sender}.
*
* Emits a {Burned} event.
*
* Requirements
*
* - the caller must have at least `amount` tokens.
*/
function burn(uint256 amount, bytes calldata data) external;
/**
* @dev Returns true if an account is an operator of `tokenHolder`.
* Operators can send and burn tokens on behalf of their owners. All
* accounts are their own operator.
*
* See {operatorSend} and {operatorBurn}.
*/
function isOperatorFor(address operator, address tokenHolder) external view returns (bool);
/**
* @dev Make an account an operator of the caller.
*
* See {isOperatorFor}.
*
* Emits an {AuthorizedOperator} event.
*
* Requirements
*
* - `operator` cannot be calling address.
*/
function authorizeOperator(address operator) external;
/**
* @dev Revoke an account's operator status for the caller.
*
* See {isOperatorFor} and {defaultOperators}.
*
* Emits a {RevokedOperator} event.
*
* Requirements
*
* - `operator` cannot be calling address.
*/
function revokeOperator(address operator) external;
/**
* @dev Returns the list of default operators. These accounts are operators
* for all token holders, even if {authorizeOperator} was never called on
* them.
*
* This list is immutable, but individual holders may revoke these via
* {revokeOperator}, in which case {isOperatorFor} will return false.
*/
function defaultOperators() external view returns (address[] memory);
/**
* @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
* be an operator of `sender`.
*
* If send or receive hooks are registered for `sender` and `recipient`,
* the corresponding functions will be called with `data` and
* `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
*
* Emits a {Sent} event.
*
* Requirements
*
* - `sender` cannot be the zero address.
* - `sender` must have at least `amount` tokens.
* - the caller must be an operator for `sender`.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function operatorSend(
address sender,
address recipient,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;
/**
* @dev Destroys `amount` tokens from `account`, reducing the total supply.
* The caller must be an operator of `account`.
*
* If a send hook is registered for `account`, the corresponding function
* will be called with `data` and `operatorData`. See {IERC777Sender}.
*
* Emits a {Burned} event.
*
* Requirements
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
* - the caller must be an operator for `account`.
*/
function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external;
event Sent(
address indexed operator,
address indexed from,
address indexed to,
uint256 amount,
bytes data,
bytes operatorData
);
}

@ -1,6 +1,34 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777Recipient.sol)
pragma solidity ^0.8.0;
import "../token/ERC777/IERC777Recipient.sol";
/**
* @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
*
* Accounts can be notified of {IERC777} tokens being sent to them by having a
* contract implement this interface (contract holders can be their own
* implementer) and registering it on the
* https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
*
* See {IERC1820Registry} and {IERC1820Implementer}.
*/
interface IERC777Recipient {
/**
* @dev Called by an {IERC777} token contract whenever tokens are being
* moved or created into a registered account (`to`). The type of operation
* is conveyed by `from` being the zero address or not.
*
* This call occurs _after_ the token contract's state is updated, so
* {IERC777-balanceOf}, etc., can be used to query the post-operation state.
*
* This function may revert to prevent the operation from being executed.
*/
function tokensReceived(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external;
}

@ -1,6 +1,34 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC777Sender.sol)
pragma solidity ^0.8.0;
import "../token/ERC777/IERC777Sender.sol";
/**
* @dev Interface of the ERC777TokensSender standard as defined in the EIP.
*
* {IERC777} Token holders can be notified of operations performed on their
* tokens by having a contract implement this interface (contract holders can be
* their own implementer) and registering it on the
* https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
*
* See {IERC1820Registry} and {IERC1820Implementer}.
*/
interface IERC777Sender {
/**
* @dev Called by an {IERC777} token contract whenever a registered holder's
* (`from`) tokens are about to be moved or destroyed. The type of operation
* is conveyed by `to` being the zero address or not.
*
* This call occurs _before_ the token contract's state is updated, so
* {IERC777-balanceOf}, etc., can be used to query the pre-operation state.
*
* This function may revert to prevent the operation from being executed.
*/
function tokensToSend(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external;
}

@ -1,7 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// EIP-2612 is Final as of 2022-11-01. This file is deprecated.
import "./IERC2612.sol";

@ -1,8 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../access/AccessControlCrossChain.sol";
import "../crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol";
contract AccessControlCrossChainMock is AccessControlCrossChain, CrossChainEnabledArbitrumL2 {}

@ -1,18 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/escrow/ConditionalEscrow.sol";
// mock class using ConditionalEscrow
contract ConditionalEscrowMock is ConditionalEscrow {
mapping(address => bool) private _allowed;
function setAllowed(address payee, bool allowed) public {
_allowed[payee] = allowed;
}
function withdrawalAllowed(address payee) public view override returns (bool) {
return _allowed[payee];
}
}

@ -1,15 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../security/PullPayment.sol";
// mock class using PullPayment
contract PullPaymentMock is PullPayment {
constructor() payable {}
// test helper function to call asyncTransfer
function callTransfer(address dest, uint256 amount) public {
_asyncTransfer(dest, amount);
}
}

@ -1,72 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/math/SafeMath.sol";
library SafeMathMemoryCheck {
function addMemoryCheck() internal pure returns (uint256 mem) {
uint256 length = 32;
assembly {
mem := mload(0x40)
}
for (uint256 i = 0; i < length; ++i) {
SafeMath.add(1, 1);
}
assembly {
mem := sub(mload(0x40), mem)
}
}
function subMemoryCheck() internal pure returns (uint256 mem) {
uint256 length = 32;
assembly {
mem := mload(0x40)
}
for (uint256 i = 0; i < length; ++i) {
SafeMath.sub(1, 1);
}
assembly {
mem := sub(mload(0x40), mem)
}
}
function mulMemoryCheck() internal pure returns (uint256 mem) {
uint256 length = 32;
assembly {
mem := mload(0x40)
}
for (uint256 i = 0; i < length; ++i) {
SafeMath.mul(1, 1);
}
assembly {
mem := sub(mload(0x40), mem)
}
}
function divMemoryCheck() internal pure returns (uint256 mem) {
uint256 length = 32;
assembly {
mem := mload(0x40)
}
for (uint256 i = 0; i < length; ++i) {
SafeMath.div(1, 1);
}
assembly {
mem := sub(mload(0x40), mem)
}
}
function modMemoryCheck() internal pure returns (uint256 mem) {
uint256 length = 32;
assembly {
mem := mload(0x40)
}
for (uint256 i = 0; i < length; ++i) {
SafeMath.mod(1, 1);
}
assembly {
mem := sub(mload(0x40), mem)
}
}
}

@ -1,39 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/Timers.sol";
contract TimersBlockNumberImpl {
using Timers for Timers.BlockNumber;
Timers.BlockNumber private _timer;
function getDeadline() public view returns (uint64) {
return _timer.getDeadline();
}
function setDeadline(uint64 timestamp) public {
_timer.setDeadline(timestamp);
}
function reset() public {
_timer.reset();
}
function isUnset() public view returns (bool) {
return _timer.isUnset();
}
function isStarted() public view returns (bool) {
return _timer.isStarted();
}
function isPending() public view returns (bool) {
return _timer.isPending();
}
function isExpired() public view returns (bool) {
return _timer.isExpired();
}
}

@ -1,39 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/Timers.sol";
contract TimersTimestampImpl {
using Timers for Timers.Timestamp;
Timers.Timestamp private _timer;
function getDeadline() public view returns (uint64) {
return _timer.getDeadline();
}
function setDeadline(uint64 timestamp) public {
_timer.setDeadline(timestamp);
}
function reset() public {
_timer.reset();
}
function isUnset() public view returns (bool) {
return _timer.isUnset();
}
function isStarted() public view returns (bool) {
return _timer.isStarted();
}
function isPending() public view returns (bool) {
return _timer.isPending();
}
function isExpired() public view returns (bool) {
return _timer.isExpired();
}
}

@ -1,94 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../utils/Address.sol";
import "../../vendor/polygon/IFxMessageProcessor.sol";
abstract contract BaseRelayMock {
// needed to parse custom errors
error NotCrossChainCall();
error InvalidCrossChainSender(address sender, address expected);
address internal _currentSender;
function relayAs(address target, bytes calldata data, address sender) external virtual {
address previousSender = _currentSender;
_currentSender = sender;
(bool success, bytes memory returndata) = target.call(data);
Address.verifyCallResultFromTarget(target, success, returndata, "low-level call reverted");
_currentSender = previousSender;
}
}
/**
* AMB
*/
contract BridgeAMBMock is BaseRelayMock {
function messageSender() public view returns (address) {
return _currentSender;
}
}
/**
* Arbitrum
*/
contract BridgeArbitrumL1Mock is BaseRelayMock {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address public immutable inbox = address(new BridgeArbitrumL1Inbox());
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address public immutable outbox = address(new BridgeArbitrumL1Outbox());
function activeOutbox() public view returns (address) {
return outbox;
}
function currentSender() public view returns (address) {
return _currentSender;
}
}
contract BridgeArbitrumL1Inbox {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address public immutable bridge = msg.sender;
}
contract BridgeArbitrumL1Outbox {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address public immutable bridge = msg.sender;
function l2ToL1Sender() public view returns (address) {
return BridgeArbitrumL1Mock(bridge).currentSender();
}
}
contract BridgeArbitrumL2Mock is BaseRelayMock {
function wasMyCallersAddressAliased() public view returns (bool) {
return _currentSender != address(0);
}
function myCallersAddressWithoutAliasing() public view returns (address) {
return _currentSender;
}
}
/**
* Optimism
*/
contract BridgeOptimismMock is BaseRelayMock {
function xDomainMessageSender() public view returns (address) {
return _currentSender;
}
}
/**
* Polygon
*/
contract BridgePolygonChildMock is BaseRelayMock {
function relayAs(address target, bytes calldata data, address sender) external override {
IFxMessageProcessor(target).processMessageFromRoot(0, sender, data);
}
}

@ -1,54 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../../access/Ownable.sol";
import "../../crosschain/amb/CrossChainEnabledAMB.sol";
import "../../crosschain/arbitrum/CrossChainEnabledArbitrumL1.sol";
import "../../crosschain/arbitrum/CrossChainEnabledArbitrumL2.sol";
import "../../crosschain/optimism/CrossChainEnabledOptimism.sol";
import "../../crosschain/polygon/CrossChainEnabledPolygonChild.sol";
abstract contract Receiver is CrossChainEnabled {
// we don't use Ownable because it messes up testing for the upgradeable contracts
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address public immutable owner = msg.sender;
function crossChainRestricted() external onlyCrossChain {}
function crossChainOwnerRestricted() external onlyCrossChainSender(owner) {}
}
/**
* AMB
*/
contract CrossChainEnabledAMBMock is Receiver, CrossChainEnabledAMB {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address bridge) CrossChainEnabledAMB(bridge) {}
}
/**
* Arbitrum
*/
contract CrossChainEnabledArbitrumL1Mock is Receiver, CrossChainEnabledArbitrumL1 {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address bridge) CrossChainEnabledArbitrumL1(bridge) {}
}
contract CrossChainEnabledArbitrumL2Mock is Receiver, CrossChainEnabledArbitrumL2 {}
/**
* Optimism
*/
contract CrossChainEnabledOptimismMock is Receiver, CrossChainEnabledOptimism {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address bridge) CrossChainEnabledOptimism(bridge) {}
}
/**
* Polygon
*/
contract CrossChainEnabledPolygonChildMock is Receiver, CrossChainEnabledPolygonChild {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor(address bridge) CrossChainEnabledPolygonChild(bridge) {}
}

@ -2,27 +2,12 @@
pragma solidity ^0.8.0;
import "../../governance/extensions/GovernorProposalThreshold.sol";
import "../../governance/extensions/GovernorSettings.sol";
import "../../governance/extensions/GovernorCountingSimple.sol";
import "../../governance/extensions/GovernorVotesQuorumFraction.sol";
abstract contract GovernorMock is
GovernorProposalThreshold,
GovernorSettings,
GovernorVotesQuorumFraction,
GovernorCountingSimple
{
abstract contract GovernorMock is GovernorSettings, GovernorVotesQuorumFraction, GovernorCountingSimple {
function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
return super.proposalThreshold();
}
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public override(Governor, GovernorProposalThreshold) returns (uint256) {
return super.propose(targets, values, calldatas, description);
}
}

@ -3,7 +3,7 @@
pragma solidity ^0.8.0;
import "../../token/ERC20/ERC20.sol";
import "../../token/ERC20/extensions/draft-ERC20Permit.sol";
import "../../token/ERC20/extensions/ERC20Permit.sol";
abstract contract ERC20PermitNoRevertMock is ERC20Permit {
function permitThatMayRevert(

@ -5,7 +5,7 @@ pragma solidity ^0.8.0;
import "../../token/ERC721/extensions/ERC721Consecutive.sol";
import "../../token/ERC721/extensions/ERC721Enumerable.sol";
import "../../token/ERC721/extensions/ERC721Pausable.sol";
import "../../token/ERC721/extensions/draft-ERC721Votes.sol";
import "../../token/ERC721/extensions/ERC721Votes.sol";
/**
* @title ERC721ConsecutiveMock

@ -1,13 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../token/ERC777/ERC777.sol";
abstract contract ERC777Mock is ERC777 {
event BeforeTokenTransfer();
function _beforeTokenTransfer(address, address, address, uint256) internal override {
emit BeforeTokenTransfer();
}
}

@ -1,152 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../token/ERC777/IERC777.sol";
import "../../token/ERC777/IERC777Sender.sol";
import "../../token/ERC777/IERC777Recipient.sol";
import "../../utils/Context.sol";
import "../../utils/introspection/IERC1820Registry.sol";
import "../../utils/introspection/ERC1820Implementer.sol";
contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient, ERC1820Implementer {
event TokensToSendCalled(
address operator,
address from,
address to,
uint256 amount,
bytes data,
bytes operatorData,
address token,
uint256 fromBalance,
uint256 toBalance
);
event TokensReceivedCalled(
address operator,
address from,
address to,
uint256 amount,
bytes data,
bytes operatorData,
address token,
uint256 fromBalance,
uint256 toBalance
);
// Emitted in ERC777Mock. Here for easier decoding
event BeforeTokenTransfer();
bool private _shouldRevertSend;
bool private _shouldRevertReceive;
IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
function tokensToSend(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external override {
if (_shouldRevertSend) {
revert();
}
IERC777 token = IERC777(_msgSender());
uint256 fromBalance = token.balanceOf(from);
// when called due to burn, to will be the zero address, which will have a balance of 0
uint256 toBalance = token.balanceOf(to);
emit TokensToSendCalled(
operator,
from,
to,
amount,
userData,
operatorData,
address(token),
fromBalance,
toBalance
);
}
function tokensReceived(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external override {
if (_shouldRevertReceive) {
revert();
}
IERC777 token = IERC777(_msgSender());
uint256 fromBalance = token.balanceOf(from);
// when called due to burn, to will be the zero address, which will have a balance of 0
uint256 toBalance = token.balanceOf(to);
emit TokensReceivedCalled(
operator,
from,
to,
amount,
userData,
operatorData,
address(token),
fromBalance,
toBalance
);
}
function senderFor(address account) public {
_registerInterfaceForAddress(_TOKENS_SENDER_INTERFACE_HASH, account);
address self = address(this);
if (account == self) {
registerSender(self);
}
}
function registerSender(address sender) public {
_erc1820.setInterfaceImplementer(address(this), _TOKENS_SENDER_INTERFACE_HASH, sender);
}
function recipientFor(address account) public {
_registerInterfaceForAddress(_TOKENS_RECIPIENT_INTERFACE_HASH, account);
address self = address(this);
if (account == self) {
registerRecipient(self);
}
}
function registerRecipient(address recipient) public {
_erc1820.setInterfaceImplementer(address(this), _TOKENS_RECIPIENT_INTERFACE_HASH, recipient);
}
function setShouldRevertSend(bool shouldRevert) public {
_shouldRevertSend = shouldRevert;
}
function setShouldRevertReceive(bool shouldRevert) public {
_shouldRevertReceive = shouldRevert;
}
function send(IERC777 token, address to, uint256 amount, bytes memory data) public {
// This is 777's send function, not the Solidity send function
token.send(to, amount, data); // solhint-disable-line check-send-result
}
function burn(IERC777 token, uint256 amount, bytes memory data) public {
token.burn(amount, data);
}
}

@ -1,79 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "../../governance/Governor.sol";
import "../../governance/extensions/GovernorCountingSimple.sol";
import "../../governance/extensions/GovernorVotes.sol";
import "../../governance/extensions/GovernorVotesQuorumFraction.sol";
import "../../governance/extensions/GovernorTimelockControl.sol";
contract MyGovernor1 is
Governor,
GovernorTimelockControl,
GovernorVotes,
GovernorVotesQuorumFraction,
GovernorCountingSimple
{
constructor(
IVotes _token,
TimelockController _timelock
) Governor("MyGovernor") GovernorVotes(_token) GovernorVotesQuorumFraction(4) GovernorTimelockControl(_timelock) {}
function votingDelay() public pure override returns (uint256) {
return 1; // 1 block
}
function votingPeriod() public pure override returns (uint256) {
return 45818; // 1 week
}
// The following functions are overrides required by Solidity.
function quorum(
uint256 blockNumber
) public view override(IGovernor, GovernorVotesQuorumFraction) returns (uint256) {
return super.quorum(blockNumber);
}
function state(uint256 proposalId) public view override(Governor, GovernorTimelockControl) returns (ProposalState) {
return super.state(proposalId);
}
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public override(Governor, IGovernor) returns (uint256) {
return super.propose(targets, values, calldatas, description);
}
function _execute(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) {
super._execute(proposalId, targets, values, calldatas, descriptionHash);
}
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) returns (uint256) {
return super._cancel(targets, values, calldatas, descriptionHash);
}
function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
return super._executor();
}
function supportsInterface(
bytes4 interfaceId
) public view override(Governor, GovernorTimelockControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
}

@ -1,85 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "../../governance/Governor.sol";
import "../../governance/extensions/GovernorProposalThreshold.sol";
import "../../governance/extensions/GovernorCountingSimple.sol";
import "../../governance/extensions/GovernorVotes.sol";
import "../../governance/extensions/GovernorVotesQuorumFraction.sol";
import "../../governance/extensions/GovernorTimelockControl.sol";
contract MyGovernor2 is
Governor,
GovernorTimelockControl,
GovernorProposalThreshold,
GovernorVotes,
GovernorVotesQuorumFraction,
GovernorCountingSimple
{
constructor(
IVotes _token,
TimelockController _timelock
) Governor("MyGovernor") GovernorVotes(_token) GovernorVotesQuorumFraction(4) GovernorTimelockControl(_timelock) {}
function votingDelay() public pure override returns (uint256) {
return 1; // 1 block
}
function votingPeriod() public pure override returns (uint256) {
return 45818; // 1 week
}
function proposalThreshold() public pure override returns (uint256) {
return 1000e18;
}
// The following functions are overrides required by Solidity.
function quorum(
uint256 blockNumber
) public view override(IGovernor, GovernorVotesQuorumFraction) returns (uint256) {
return super.quorum(blockNumber);
}
function state(uint256 proposalId) public view override(Governor, GovernorTimelockControl) returns (ProposalState) {
return super.state(proposalId);
}
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public override(Governor, GovernorProposalThreshold, IGovernor) returns (uint256) {
return super.propose(targets, values, calldatas, description);
}
function _execute(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) {
super._execute(proposalId, targets, values, calldatas, descriptionHash);
}
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) returns (uint256) {
return super._cancel(targets, values, calldatas, descriptionHash);
}
function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
return super._executor();
}
function supportsInterface(
bytes4 interfaceId
) public view override(Governor, GovernorTimelockControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
}

@ -1,94 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "../../governance/Governor.sol";
import "../../governance/compatibility/GovernorCompatibilityBravo.sol";
import "../../governance/extensions/GovernorVotes.sol";
import "../../governance/extensions/GovernorVotesQuorumFraction.sol";
import "../../governance/extensions/GovernorTimelockControl.sol";
contract MyGovernor is
Governor,
GovernorTimelockControl,
GovernorCompatibilityBravo,
GovernorVotes,
GovernorVotesQuorumFraction
{
constructor(
IVotes _token,
TimelockController _timelock
) Governor("MyGovernor") GovernorVotes(_token) GovernorVotesQuorumFraction(4) GovernorTimelockControl(_timelock) {}
function votingDelay() public pure override returns (uint256) {
return 1; // 1 block
}
function votingPeriod() public pure override returns (uint256) {
return 45818; // 1 week
}
function proposalThreshold() public pure override returns (uint256) {
return 1000e18;
}
// The following functions are overrides required by Solidity.
function quorum(
uint256 blockNumber
) public view override(IGovernor, GovernorVotesQuorumFraction) returns (uint256) {
return super.quorum(blockNumber);
}
function state(
uint256 proposalId
) public view override(Governor, IGovernor, GovernorTimelockControl) returns (ProposalState) {
return super.state(proposalId);
}
function propose(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
string memory description
) public override(Governor, GovernorCompatibilityBravo, IGovernor) returns (uint256) {
return super.propose(targets, values, calldatas, description);
}
function cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public override(Governor, GovernorCompatibilityBravo, IGovernor) returns (uint256) {
return super.cancel(targets, values, calldatas, descriptionHash);
}
function _execute(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) {
super._execute(proposalId, targets, values, calldatas, descriptionHash);
}
function _cancel(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) returns (uint256) {
return super._cancel(targets, values, calldatas, descriptionHash);
}
function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
return super._executor();
}
function supportsInterface(
bytes4 interfaceId
) public view override(Governor, IERC165, GovernorTimelockControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
}

@ -31,31 +31,10 @@ contract BeaconProxy is Proxy, ERC1967Upgrade {
_upgradeBeaconToAndCall(beacon, data, false);
}
/**
* @dev Returns the current beacon address.
*/
function _beacon() internal view virtual returns (address) {
return _getBeacon();
}
/**
* @dev Returns the current implementation address of the associated beacon.
*/
function _implementation() internal view virtual override returns (address) {
return IBeacon(_getBeacon()).implementation();
}
/**
* @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.
*
* If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.
*
* Requirements:
*
* - `beacon` must be a contract.
* - The implementation returned by `beacon` must be a contract.
*/
function _setBeacon(address beacon, bytes memory data) internal virtual {
_upgradeBeaconToAndCall(beacon, data, false);
}
}

@ -60,20 +60,6 @@ contract TransparentUpgradeableProxy is ERC1967Proxy {
_changeAdmin(admin_);
}
/**
* @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
*
* CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the
* implementation provides a function with the same selector.
*/
modifier ifAdmin() {
if (msg.sender == _getAdmin()) {
_;
} else {
_fallback();
}
}
/**
* @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior
*/
@ -137,17 +123,8 @@ contract TransparentUpgradeableProxy is ERC1967Proxy {
}
/**
* @dev Returns the current admin.
*
* CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead.
*/
function _admin() internal view virtual returns (address) {
return _getAdmin();
}
/**
* @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to
* emulate some proxy functions being non-payable while still allowing value to pass through.
* @dev To keep this contract fully transparent, the fallback is payable. This helper is here to enforce
* non-payability of function implemented through dispatchers while still allowing value to pass through.
*/
function _requireZeroValue() private {
require(msg.value == 0);

@ -1,74 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/PullPayment.sol)
pragma solidity ^0.8.0;
import "../utils/escrow/Escrow.sol";
/**
* @dev Simple implementation of a
* https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#favor-pull-over-push-for-external-calls[pull-payment]
* strategy, where the paying contract doesn't interact directly with the
* receiver account, which must withdraw its payments itself.
*
* Pull-payments are often considered the best practice when it comes to sending
* Ether, security-wise. It prevents recipients from blocking execution, and
* eliminates reentrancy concerns.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*
* To use, derive from the `PullPayment` contract, and use {_asyncTransfer}
* instead of Solidity's `transfer` function. Payees can query their due
* payments with {payments}, and retrieve them with {withdrawPayments}.
*/
abstract contract PullPayment {
Escrow private immutable _escrow;
constructor() {
_escrow = new Escrow();
}
/**
* @dev Withdraw accumulated payments, forwarding all gas to the recipient.
*
* Note that _any_ account can call this function, not just the `payee`.
* This means that contracts unaware of the `PullPayment` protocol can still
* receive funds this way, by having a separate account call
* {withdrawPayments}.
*
* WARNING: Forwarding all gas opens the door to reentrancy vulnerabilities.
* Make sure you trust the recipient, or are either following the
* checks-effects-interactions pattern or using {ReentrancyGuard}.
*
* @param payee Whose payments will be withdrawn.
*
* Causes the `escrow` to emit a {Withdrawn} event.
*/
function withdrawPayments(address payable payee) public virtual {
_escrow.withdraw(payee);
}
/**
* @dev Returns the payments owed to an address.
* @param dest The creditor's address.
*/
function payments(address dest) public view returns (uint256) {
return _escrow.depositsOf(dest);
}
/**
* @dev Called by the payer to store the sent amount as credit to be pulled.
* Funds sent in this way are stored in an intermediate {Escrow} contract, so
* there is no danger of them being spent before withdrawal.
*
* @param dest The destination address of the funds.
* @param amount The amount to transfer.
*
* Causes the `escrow` to emit a {Deposited} event.
*/
function _asyncTransfer(address dest, uint256 amount) internal virtual {
_escrow.deposit{value: amount}(dest);
}
}

@ -5,7 +5,6 @@ NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/
These contracts aim to cover common security practices.
* {PullPayment}: A pattern that can be used to avoid reentrancy attacks.
* {ReentrancyGuard}: A modifier that can prevent reentrancy during certain functions.
* {Pausable}: A common emergency response mechanism that can pause functionality while a remediation is pending.
@ -13,8 +12,6 @@ TIP: For an overview on reentrancy and the possible mechanisms to prevent it, re
== Contracts
{{PullPayment}}
{{ReentrancyGuard}}
{{Pausable}}

@ -23,14 +23,6 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {
// solhint-disable-next-line var-name-mixedcase
bytes32 private constant _PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
/**
* @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
* However, to ensure consistency with the upgradeable transpiler, we will continue
* to reserve a slot.
* @custom:oz-renamed-from _PERMIT_TYPEHASH
*/
// solhint-disable-next-line var-name-mixedcase
bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;
/**
* @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.

@ -1,8 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)
pragma solidity ^0.8.0;
// EIP-2612 is Final as of 2022-11-01. This file is deprecated.
import "./ERC20Permit.sol";

@ -1,7 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// EIP-2612 is Final as of 2022-11-01. This file is deprecated.
import "./IERC20Permit.sol";

@ -35,24 +35,6 @@ library SafeERC20 {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.

@ -1,9 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/draft-ERC721Votes.sol)
pragma solidity ^0.8.0;
// ERC721Votes was marked as draft due to the EIP-712 dependency.
// EIP-712 is Final as of 2022-08-11. This file is deprecated.
import "./ERC721Votes.sol";

@ -1,517 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC777/ERC777.sol)
pragma solidity ^0.8.1;
import "./IERC777.sol";
import "./IERC777Recipient.sol";
import "./IERC777Sender.sol";
import "../ERC20/IERC20.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/introspection/IERC1820Registry.sol";
/**
* @dev Implementation of the {IERC777} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* Support for ERC20 is included in this contract, as specified by the EIP: both
* the ERC777 and ERC20 interfaces can be safely used when interacting with it.
* Both {IERC777-Sent} and {IERC20-Transfer} events are emitted on token
* movements.
*
* Additionally, the {IERC777-granularity} value is hard-coded to `1`, meaning that there
* are no special restrictions in the amount of tokens that created, moved, or
* destroyed. This makes integration with ERC20 applications seamless.
*
* CAUTION: This file is deprecated as of v4.9 and will be removed in the next major release.
*/
contract ERC777 is Context, IERC777, IERC20 {
using Address for address;
IERC1820Registry internal constant _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
mapping(address => uint256) private _balances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
// This isn't ever read from - it's only used to respond to the defaultOperators query.
address[] private _defaultOperatorsArray;
// Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
mapping(address => bool) private _defaultOperators;
// For each account, a mapping of its operators and revoked default operators.
mapping(address => mapping(address => bool)) private _operators;
mapping(address => mapping(address => bool)) private _revokedDefaultOperators;
// ERC20-allowances
mapping(address => mapping(address => uint256)) private _allowances;
/**
* @dev `defaultOperators` may be an empty array.
*/
constructor(string memory name_, string memory symbol_, address[] memory defaultOperators_) {
_name = name_;
_symbol = symbol_;
_defaultOperatorsArray = defaultOperators_;
for (uint256 i = 0; i < defaultOperators_.length; i++) {
_defaultOperators[defaultOperators_[i]] = true;
}
// register interfaces
_ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
_ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
}
/**
* @dev See {IERC777-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC777-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {ERC20-decimals}.
*
* Always returns 18, as per the
* [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
*/
function decimals() public pure virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC777-granularity}.
*
* This implementation always returns `1`.
*/
function granularity() public view virtual override returns (uint256) {
return 1;
}
/**
* @dev See {IERC777-totalSupply}.
*/
function totalSupply() public view virtual override(IERC20, IERC777) returns (uint256) {
return _totalSupply;
}
/**
* @dev Returns the amount of tokens owned by an account (`tokenHolder`).
*/
function balanceOf(address tokenHolder) public view virtual override(IERC20, IERC777) returns (uint256) {
return _balances[tokenHolder];
}
/**
* @dev See {IERC777-send}.
*
* Also emits a {IERC20-Transfer} event for ERC20 compatibility.
*/
function send(address recipient, uint256 amount, bytes memory data) public virtual override {
_send(_msgSender(), recipient, amount, data, "", true);
}
/**
* @dev See {IERC20-transfer}.
*
* Unlike `send`, `recipient` is _not_ required to implement the {IERC777Recipient}
* interface if it is a contract.
*
* Also emits a {Sent} event.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_send(_msgSender(), recipient, amount, "", "", false);
return true;
}
/**
* @dev See {IERC777-burn}.
*
* Also emits a {IERC20-Transfer} event for ERC20 compatibility.
*/
function burn(uint256 amount, bytes memory data) public virtual override {
_burn(_msgSender(), amount, data, "");
}
/**
* @dev See {IERC777-isOperatorFor}.
*/
function isOperatorFor(address operator, address tokenHolder) public view virtual override returns (bool) {
return
operator == tokenHolder ||
(_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
_operators[tokenHolder][operator];
}
/**
* @dev See {IERC777-authorizeOperator}.
*/
function authorizeOperator(address operator) public virtual override {
require(_msgSender() != operator, "ERC777: authorizing self as operator");
if (_defaultOperators[operator]) {
delete _revokedDefaultOperators[_msgSender()][operator];
} else {
_operators[_msgSender()][operator] = true;
}
emit AuthorizedOperator(operator, _msgSender());
}
/**
* @dev See {IERC777-revokeOperator}.
*/
function revokeOperator(address operator) public virtual override {
require(operator != _msgSender(), "ERC777: revoking self as operator");
if (_defaultOperators[operator]) {
_revokedDefaultOperators[_msgSender()][operator] = true;
} else {
delete _operators[_msgSender()][operator];
}
emit RevokedOperator(operator, _msgSender());
}
/**
* @dev See {IERC777-defaultOperators}.
*/
function defaultOperators() public view virtual override returns (address[] memory) {
return _defaultOperatorsArray;
}
/**
* @dev See {IERC777-operatorSend}.
*
* Emits {Sent} and {IERC20-Transfer} events.
*/
function operatorSend(
address sender,
address recipient,
uint256 amount,
bytes memory data,
bytes memory operatorData
) public virtual override {
require(isOperatorFor(_msgSender(), sender), "ERC777: caller is not an operator for holder");
_send(sender, recipient, amount, data, operatorData, true);
}
/**
* @dev See {IERC777-operatorBurn}.
*
* Emits {Burned} and {IERC20-Transfer} events.
*/
function operatorBurn(
address account,
uint256 amount,
bytes memory data,
bytes memory operatorData
) public virtual override {
require(isOperatorFor(_msgSender(), account), "ERC777: caller is not an operator for holder");
_burn(account, amount, data, operatorData);
}
/**
* @dev See {IERC20-allowance}.
*
* Note that operator and allowance concepts are orthogonal: operators may
* not have allowance, and accounts with allowance may not be operators
* themselves.
*/
function allowance(address holder, address spender) public view virtual override returns (uint256) {
return _allowances[holder][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Note that accounts cannot have allowance issued by their operators.
*/
function approve(address spender, uint256 value) public virtual override returns (bool) {
address holder = _msgSender();
_approve(holder, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Note that operator and allowance concepts are orthogonal: operators cannot
* call `transferFrom` (unless they have allowance), and accounts with
* allowance cannot call `operatorSend` (unless they are operators).
*
* Emits {Sent}, {IERC20-Transfer} and {IERC20-Approval} events.
*/
function transferFrom(address holder, address recipient, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(holder, spender, amount);
_send(holder, recipient, amount, "", "", false);
return true;
}
/**
* @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* If a send hook is registered for `account`, the corresponding function
* will be called with the caller address as the `operator` and with
* `userData` and `operatorData`.
*
* See {IERC777Sender} and {IERC777Recipient}.
*
* Emits {Minted} and {IERC20-Transfer} events.
*
* Requirements
*
* - `account` cannot be the zero address.
* - if `account` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function _mint(address account, uint256 amount, bytes memory userData, bytes memory operatorData) internal virtual {
_mint(account, amount, userData, operatorData, true);
}
/**
* @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* If `requireReceptionAck` is set to true, and if a send hook is
* registered for `account`, the corresponding function will be called with
* `operator`, `data` and `operatorData`.
*
* See {IERC777Sender} and {IERC777Recipient}.
*
* Emits {Minted} and {IERC20-Transfer} events.
*
* Requirements
*
* - `account` cannot be the zero address.
* - if `account` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function _mint(
address account,
uint256 amount,
bytes memory userData,
bytes memory operatorData,
bool requireReceptionAck
) internal virtual {
require(account != address(0), "ERC777: mint to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), account, amount);
// Update state variables
_totalSupply += amount;
_balances[account] += amount;
_callTokensReceived(operator, address(0), account, amount, userData, operatorData, requireReceptionAck);
emit Minted(operator, account, amount, userData, operatorData);
emit Transfer(address(0), account, amount);
}
/**
* @dev Send tokens
* @param from address token holder address
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param userData bytes extra information provided by the token holder (if any)
* @param operatorData bytes extra information provided by the operator (if any)
* @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
*/
function _send(
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData,
bool requireReceptionAck
) internal virtual {
require(from != address(0), "ERC777: transfer from the zero address");
require(to != address(0), "ERC777: transfer to the zero address");
address operator = _msgSender();
_callTokensToSend(operator, from, to, amount, userData, operatorData);
_move(operator, from, to, amount, userData, operatorData);
_callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);
}
/**
* @dev Burn tokens
* @param from address token holder address
* @param amount uint256 amount of tokens to burn
* @param data bytes extra information provided by the token holder
* @param operatorData bytes extra information provided by the operator (if any)
*/
function _burn(address from, uint256 amount, bytes memory data, bytes memory operatorData) internal virtual {
require(from != address(0), "ERC777: burn from the zero address");
address operator = _msgSender();
_callTokensToSend(operator, from, address(0), amount, data, operatorData);
_beforeTokenTransfer(operator, from, address(0), amount);
// Update state variables
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC777: burn amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_totalSupply -= amount;
emit Burned(operator, from, amount, data, operatorData);
emit Transfer(from, address(0), amount);
}
function _move(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
) private {
_beforeTokenTransfer(operator, from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC777: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Sent(operator, from, to, amount, userData, operatorData);
emit Transfer(from, to, amount);
}
/**
* @dev See {ERC20-_approve}.
*
* Note that accounts cannot have allowance issued by their operators.
*/
function _approve(address holder, address spender, uint256 value) internal virtual {
require(holder != address(0), "ERC777: approve from the zero address");
require(spender != address(0), "ERC777: approve to the zero address");
_allowances[holder][spender] = value;
emit Approval(holder, spender, value);
}
/**
* @dev Call from.tokensToSend() if the interface is registered
* @param operator address operator requesting the transfer
* @param from address token holder address
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param userData bytes extra information provided by the token holder (if any)
* @param operatorData bytes extra information provided by the operator (if any)
*/
function _callTokensToSend(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
) private {
address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(from, _TOKENS_SENDER_INTERFACE_HASH);
if (implementer != address(0)) {
IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
}
}
/**
* @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
* tokensReceived() was not registered for the recipient
* @param operator address operator requesting the transfer
* @param from address token holder address
* @param to address recipient address
* @param amount uint256 amount of tokens to transfer
* @param userData bytes extra information provided by the token holder (if any)
* @param operatorData bytes extra information provided by the operator (if any)
* @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
*/
function _callTokensReceived(
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData,
bool requireReceptionAck
) private {
address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(to, _TOKENS_RECIPIENT_INTERFACE_HASH);
if (implementer != address(0)) {
IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
} else if (requireReceptionAck) {
require(
to.code.length == 0,
"ERC777: token recipient contract has no implementer for ERC777TokensRecipient"
);
}
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {IERC20-Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC777: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any token transfer. This includes
* calls to {send}, {transfer}, {operatorSend}, {transferFrom}, minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be to transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address operator, address from, address to, uint256 amount) internal virtual {}
}

@ -1,200 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC777/IERC777.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC777Token standard as defined in the EIP.
*
* This contract uses the
* https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
* token holders and recipients react to token movements by using setting implementers
* for the associated interfaces in said registry. See {IERC1820Registry} and
* {ERC1820Implementer}.
*/
interface IERC777 {
/**
* @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`.
*
* Note that some additional user `data` and `operatorData` can be logged in the event.
*/
event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
/**
* @dev Emitted when `operator` destroys `amount` tokens from `account`.
*
* Note that some additional user `data` and `operatorData` can be logged in the event.
*/
event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
/**
* @dev Emitted when `operator` is made operator for `tokenHolder`.
*/
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
/**
* @dev Emitted when `operator` is revoked its operator status for `tokenHolder`.
*/
event RevokedOperator(address indexed operator, address indexed tokenHolder);
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the smallest part of the token that is not divisible. This
* means all token operations (creation, movement and destruction) must have
* amounts that are a multiple of this number.
*
* For most token contracts, this value will equal 1.
*/
function granularity() external view returns (uint256);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by an account (`owner`).
*/
function balanceOf(address owner) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* If send or receive hooks are registered for the caller and `recipient`,
* the corresponding functions will be called with `data` and empty
* `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
*
* Emits a {Sent} event.
*
* Requirements
*
* - the caller must have at least `amount` tokens.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function send(address recipient, uint256 amount, bytes calldata data) external;
/**
* @dev Destroys `amount` tokens from the caller's account, reducing the
* total supply.
*
* If a send hook is registered for the caller, the corresponding function
* will be called with `data` and empty `operatorData`. See {IERC777Sender}.
*
* Emits a {Burned} event.
*
* Requirements
*
* - the caller must have at least `amount` tokens.
*/
function burn(uint256 amount, bytes calldata data) external;
/**
* @dev Returns true if an account is an operator of `tokenHolder`.
* Operators can send and burn tokens on behalf of their owners. All
* accounts are their own operator.
*
* See {operatorSend} and {operatorBurn}.
*/
function isOperatorFor(address operator, address tokenHolder) external view returns (bool);
/**
* @dev Make an account an operator of the caller.
*
* See {isOperatorFor}.
*
* Emits an {AuthorizedOperator} event.
*
* Requirements
*
* - `operator` cannot be calling address.
*/
function authorizeOperator(address operator) external;
/**
* @dev Revoke an account's operator status for the caller.
*
* See {isOperatorFor} and {defaultOperators}.
*
* Emits a {RevokedOperator} event.
*
* Requirements
*
* - `operator` cannot be calling address.
*/
function revokeOperator(address operator) external;
/**
* @dev Returns the list of default operators. These accounts are operators
* for all token holders, even if {authorizeOperator} was never called on
* them.
*
* This list is immutable, but individual holders may revoke these via
* {revokeOperator}, in which case {isOperatorFor} will return false.
*/
function defaultOperators() external view returns (address[] memory);
/**
* @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
* be an operator of `sender`.
*
* If send or receive hooks are registered for `sender` and `recipient`,
* the corresponding functions will be called with `data` and
* `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
*
* Emits a {Sent} event.
*
* Requirements
*
* - `sender` cannot be the zero address.
* - `sender` must have at least `amount` tokens.
* - the caller must be an operator for `sender`.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function operatorSend(
address sender,
address recipient,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;
/**
* @dev Destroys `amount` tokens from `account`, reducing the total supply.
* The caller must be an operator of `account`.
*
* If a send hook is registered for `account`, the corresponding function
* will be called with `data` and `operatorData`. See {IERC777Sender}.
*
* Emits a {Burned} event.
*
* Requirements
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
* - the caller must be an operator for `account`.
*/
function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external;
event Sent(
address indexed operator,
address indexed from,
address indexed to,
uint256 amount,
bytes data,
bytes operatorData
);
}

@ -1,35 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
*
* Accounts can be notified of {IERC777} tokens being sent to them by having a
* contract implement this interface (contract holders can be their own
* implementer) and registering it on the
* https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
*
* See {IERC1820Registry} and {ERC1820Implementer}.
*/
interface IERC777Recipient {
/**
* @dev Called by an {IERC777} token contract whenever tokens are being
* moved or created into a registered account (`to`). The type of operation
* is conveyed by `from` being the zero address or not.
*
* This call occurs _after_ the token contract's state is updated, so
* {IERC777-balanceOf}, etc., can be used to query the post-operation state.
*
* This function may revert to prevent the operation from being executed.
*/
function tokensReceived(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external;
}

@ -1,35 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Sender.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC777TokensSender standard as defined in the EIP.
*
* {IERC777} Token holders can be notified of operations performed on their
* tokens by having a contract implement this interface (contract holders can be
* their own implementer) and registering it on the
* https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
*
* See {IERC1820Registry} and {ERC1820Implementer}.
*/
interface IERC777Sender {
/**
* @dev Called by an {IERC777} token contract whenever a registered holder's
* (`from`) tokens are about to be moved or destroyed. The type of operation
* is conveyed by `to` being the zero address or not.
*
* This call occurs _before_ the token contract's state is updated, so
* {IERC777-balanceOf}, etc., can be used to query the pre-operation state.
*
* This function may revert to prevent the operation from being executed.
*/
function tokensToSend(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external;
}

@ -1,26 +0,0 @@
= ERC 777
[.readme-notice]
NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc777
CAUTION: As of v4.9, OpenZeppelin's implementation of ERC-777 is deprecated and will be removed in the next major release.
This set of interfaces and contracts are all related to the https://eips.ethereum.org/EIPS/eip-777[ERC777 token standard].
TIP: For an overview of ERC777 tokens and a walk through on how to create a token contract read our xref:ROOT:erc777.adoc[ERC777 guide].
The token behavior itself is implemented in the core contracts: {IERC777}, {ERC777}.
Additionally there are interfaces used to develop contracts that react to token movements: {IERC777Sender}, {IERC777Recipient}.
== Core
{{IERC777}}
{{ERC777}}
== Hooks
{{IERC777Sender}}
{{IERC777Recipient}}

@ -17,202 +17,6 @@ import "./math/SafeCast.sol";
* _Available since v4.5._
*/
library Checkpoints {
struct History {
Checkpoint[] _checkpoints;
}
struct Checkpoint {
uint32 _blockNumber;
uint224 _value;
}
/**
* @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
* before it is returned, or zero otherwise. Because the number returned corresponds to that at the end of the
* block, the requested block number must be in the past, excluding the current block.
*/
function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
require(blockNumber < block.number, "Checkpoints: block not yet mined");
uint32 key = SafeCast.toUint32(blockNumber);
uint256 len = self._checkpoints.length;
uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
* before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched
* checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of
* checkpoints.
*/
function getAtProbablyRecentBlock(History storage self, uint256 blockNumber) internal view returns (uint256) {
require(blockNumber < block.number, "Checkpoints: block not yet mined");
uint32 key = SafeCast.toUint32(blockNumber);
uint256 len = self._checkpoints.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self._checkpoints, mid)._blockNumber) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block.
*
* Returns previous value and new value.
*/
function push(History storage self, uint256 value) internal returns (uint256, uint256) {
return _insert(self._checkpoints, SafeCast.toUint32(block.number), SafeCast.toUint224(value));
}
/**
* @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will
* be set to `op(latest, delta)`.
*
* Returns previous value and new value.
*/
function push(
History storage self,
function(uint256, uint256) view returns (uint256) op,
uint256 delta
) internal returns (uint256, uint256) {
return push(self, op(latest(self), delta));
}
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
function latest(History storage self) internal view returns (uint224) {
uint256 pos = self._checkpoints.length;
return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value;
}
/**
* @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
* in the most recent checkpoint.
*/
function latestCheckpoint(
History storage self
) internal view returns (bool exists, uint32 _blockNumber, uint224 _value) {
uint256 pos = self._checkpoints.length;
if (pos == 0) {
return (false, 0, 0);
} else {
Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, pos - 1);
return (true, ckpt._blockNumber, ckpt._value);
}
}
/**
* @dev Returns the number of checkpoint.
*/
function length(History storage self) internal view returns (uint256) {
return self._checkpoints.length;
}
/**
* @dev Returns checkpoint at given position.
*/
function at(History storage self, uint32 pos) internal view returns (Checkpoint memory) {
return self._checkpoints[pos];
}
/**
* @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
* or by updating the last one.
*/
function _insert(Checkpoint[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) {
uint256 pos = self.length;
if (pos > 0) {
// Copying to memory is important here.
Checkpoint memory last = _unsafeAccess(self, pos - 1);
// Checkpoint keys must be non-decreasing.
require(last._blockNumber <= key, "Checkpoint: decreasing keys");
// Update or push new checkpoint
if (last._blockNumber == key) {
_unsafeAccess(self, pos - 1)._value = value;
} else {
self.push(Checkpoint({_blockNumber: key, _value: value}));
}
return (last._value, value);
} else {
self.push(Checkpoint({_blockNumber: key, _value: value}));
return (0, value);
}
}
/**
* @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none.
* `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _upperBinaryLookup(
Checkpoint[] storage self,
uint32 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._blockNumber > key) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}
/**
* @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none.
* `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
*
* WARNING: `high` should not be greater than the array's length.
*/
function _lowerBinaryLookup(
Checkpoint[] storage self,
uint32 key,
uint256 low,
uint256 high
) private view returns (uint256) {
while (low < high) {
uint256 mid = Math.average(low, high);
if (_unsafeAccess(self, mid)._blockNumber < key) {
low = mid + 1;
} else {
high = mid;
}
}
return high;
}
/**
* @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
*/
function _unsafeAccess(Checkpoint[] storage self, uint256 pos) private pure returns (Checkpoint storage result) {
assembly {
mstore(0, self.slot)
result.slot := add(keccak256(0, 0x20), pos)
}
}
struct Trace224 {
Checkpoint224[] _checkpoints;
}

@ -31,10 +31,6 @@ Finally, {Create2} contains all necessary utilities to safely use the https://bl
{{SafeCast}}
{{SafeMath}}
{{SignedSafeMath}}
== Cryptography
{{ECDSA}}
@ -45,39 +41,18 @@ Finally, {Create2} contains all necessary utilities to safely use the https://bl
{{EIP712}}
== Escrow
{{ConditionalEscrow}}
{{Escrow}}
{{RefundEscrow}}
== Introspection
This set of interfaces and contracts deal with https://en.wikipedia.org/wiki/Type_introspection[type introspection] of contracts, that is, examining which functions can be called on them. This is usually referred to as a contract's _interface_.
Ethereum contracts have no native concept of an interface, so applications must usually simply trust they are not making an incorrect call. For trusted setups this is a non-issue, but often unknown and untrusted third-party addresses need to be interacted with. There may even not be any direct calls to them! (e.g. `ERC20` tokens may be sent to a contract that lacks a way to transfer them out of it, locking them forever). In these cases, a contract _declaring_ its interface can be very helpful in preventing errors.
There are two main ways to approach this.
* Locally, where a contract implements `IERC165` and declares an interface, and a second one queries it directly via `ERC165Checker`.
* Globally, where a global and unique registry (`IERC1820Registry`) is used to register implementers of a certain interface (`IERC1820Implementer`). It is then the registry that is queried, which allows for more complex setups, like contracts implementing interfaces for externally-owned accounts.
Note that, in all cases, accounts simply _declare_ their interfaces, but they are not required to actually implement them. This mechanism can therefore be used to both prevent errors and allow for complex interactions (see `ERC777`), but it must not be relied on for security.
{{IERC165}}
{{ERC165}}
{{ERC165Checker}}
{{IERC1820Registry}}
{{IERC1820Implementer}}
{{ERC1820Implementer}}
== Data Structures
{{BitMaps}}

@ -1,75 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Timers.sol)
pragma solidity ^0.8.0;
/**
* @dev Tooling for timepoints, timers and delays
*
* CAUTION: This file is deprecated as of 4.9 and will be removed in the next major release.
*/
library Timers {
struct Timestamp {
uint64 _deadline;
}
function getDeadline(Timestamp memory timer) internal pure returns (uint64) {
return timer._deadline;
}
function setDeadline(Timestamp storage timer, uint64 timestamp) internal {
timer._deadline = timestamp;
}
function reset(Timestamp storage timer) internal {
timer._deadline = 0;
}
function isUnset(Timestamp memory timer) internal pure returns (bool) {
return timer._deadline == 0;
}
function isStarted(Timestamp memory timer) internal pure returns (bool) {
return timer._deadline > 0;
}
function isPending(Timestamp memory timer) internal view returns (bool) {
return timer._deadline > block.timestamp;
}
function isExpired(Timestamp memory timer) internal view returns (bool) {
return isStarted(timer) && timer._deadline <= block.timestamp;
}
struct BlockNumber {
uint64 _deadline;
}
function getDeadline(BlockNumber memory timer) internal pure returns (uint64) {
return timer._deadline;
}
function setDeadline(BlockNumber storage timer, uint64 timestamp) internal {
timer._deadline = timestamp;
}
function reset(BlockNumber storage timer) internal {
timer._deadline = 0;
}
function isUnset(BlockNumber memory timer) internal pure returns (bool) {
return timer._deadline == 0;
}
function isStarted(BlockNumber memory timer) internal pure returns (bool) {
return timer._deadline > 0;
}
function isPending(BlockNumber memory timer) internal view returns (bool) {
return timer._deadline > block.number;
}
function isExpired(BlockNumber memory timer) internal view returns (bool) {
return isStarted(timer) && timer._deadline <= block.number;
}
}

@ -16,8 +16,7 @@ library ECDSA {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
InvalidSignatureS
}
function _throwError(RecoverError error) private pure {

@ -1,8 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)
pragma solidity ^0.8.0;
// EIP-712 is Final as of 2022-08-11. This file is deprecated.
import "./EIP712.sol";

@ -1,25 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/escrow/ConditionalEscrow.sol)
pragma solidity ^0.8.0;
import "./Escrow.sol";
/**
* @title ConditionalEscrow
* @dev Base abstract escrow to only allow withdrawal if a condition is met.
* @dev Intended usage: See {Escrow}. Same usage guidelines apply here.
*/
abstract contract ConditionalEscrow is Escrow {
/**
* @dev Returns whether an address is allowed to withdraw their funds. To be
* implemented by derived contracts.
* @param payee The destination address of the funds.
*/
function withdrawalAllowed(address payee) public view virtual returns (bool);
function withdraw(address payable payee) public virtual override {
require(withdrawalAllowed(payee), "ConditionalEscrow: payee is not allowed to withdraw");
super.withdraw(payee);
}
}

@ -1,67 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/escrow/Escrow.sol)
pragma solidity ^0.8.0;
import "../../access/Ownable.sol";
import "../Address.sol";
/**
* @title Escrow
* @dev Base escrow contract, holds funds designated for a payee until they
* withdraw them.
*
* Intended usage: This contract (and derived escrow contracts) should be a
* standalone contract, that only interacts with the contract that instantiated
* it. That way, it is guaranteed that all Ether will be handled according to
* the `Escrow` rules, and there is no need to check for payable functions or
* transfers in the inheritance tree. The contract that uses the escrow as its
* payment method should be its owner, and provide public methods redirecting
* to the escrow's deposit and withdraw.
*/
contract Escrow is Ownable {
using Address for address payable;
event Deposited(address indexed payee, uint256 weiAmount);
event Withdrawn(address indexed payee, uint256 weiAmount);
mapping(address => uint256) private _deposits;
function depositsOf(address payee) public view returns (uint256) {
return _deposits[payee];
}
/**
* @dev Stores the sent amount as credit to be withdrawn.
* @param payee The destination address of the funds.
*
* Emits a {Deposited} event.
*/
function deposit(address payee) public payable virtual onlyOwner {
uint256 amount = msg.value;
_deposits[payee] += amount;
emit Deposited(payee, amount);
}
/**
* @dev Withdraw accumulated balance for a payee, forwarding all gas to the
* recipient.
*
* WARNING: Forwarding all gas opens the door to reentrancy vulnerabilities.
* Make sure you trust the recipient, or are either following the
* checks-effects-interactions pattern or using {ReentrancyGuard}.
*
* @param payee The address whose funds will be withdrawn and transferred to.
*
* Emits a {Withdrawn} event.
*/
function withdraw(address payable payee) public virtual onlyOwner {
uint256 payment = _deposits[payee];
_deposits[payee] = 0;
payee.sendValue(payment);
emit Withdrawn(payee, payment);
}
}

@ -1,100 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/escrow/RefundEscrow.sol)
pragma solidity ^0.8.0;
import "./ConditionalEscrow.sol";
/**
* @title RefundEscrow
* @dev Escrow that holds funds for a beneficiary, deposited from multiple
* parties.
* @dev Intended usage: See {Escrow}. Same usage guidelines apply here.
* @dev The owner account (that is, the contract that instantiates this
* contract) may deposit, close the deposit period, and allow for either
* withdrawal by the beneficiary, or refunds to the depositors. All interactions
* with `RefundEscrow` will be made through the owner contract.
*/
contract RefundEscrow is ConditionalEscrow {
using Address for address payable;
enum State {
Active,
Refunding,
Closed
}
event RefundsClosed();
event RefundsEnabled();
State private _state;
address payable private immutable _beneficiary;
/**
* @dev Constructor.
* @param beneficiary_ The beneficiary of the deposits.
*/
constructor(address payable beneficiary_) {
require(beneficiary_ != address(0), "RefundEscrow: beneficiary is the zero address");
_beneficiary = beneficiary_;
_state = State.Active;
}
/**
* @return The current state of the escrow.
*/
function state() public view virtual returns (State) {
return _state;
}
/**
* @return The beneficiary of the escrow.
*/
function beneficiary() public view virtual returns (address payable) {
return _beneficiary;
}
/**
* @dev Stores funds that may later be refunded.
* @param refundee The address funds will be sent to if a refund occurs.
*/
function deposit(address refundee) public payable virtual override {
require(state() == State.Active, "RefundEscrow: can only deposit while active");
super.deposit(refundee);
}
/**
* @dev Allows for the beneficiary to withdraw their funds, rejecting
* further deposits.
*/
function close() public virtual onlyOwner {
require(state() == State.Active, "RefundEscrow: can only close while active");
_state = State.Closed;
emit RefundsClosed();
}
/**
* @dev Allows for refunds to take place, rejecting further deposits.
*/
function enableRefunds() public virtual onlyOwner {
require(state() == State.Active, "RefundEscrow: can only enable refunds while active");
_state = State.Refunding;
emit RefundsEnabled();
}
/**
* @dev Withdraws the beneficiary's funds.
*/
function beneficiaryWithdraw() public virtual {
require(state() == State.Closed, "RefundEscrow: beneficiary can only withdraw while closed");
beneficiary().sendValue(address(this).balance);
}
/**
* @dev Returns whether refundees can withdraw their deposits (be refunded). The overridden function receives a
* 'payee' argument, but we ignore it here since the condition is global, not per-payee.
*/
function withdrawalAllowed(address) public view override returns (bool) {
return state() == State.Refunding;
}
}

@ -1,43 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC1820Implementer.sol)
pragma solidity ^0.8.0;
import "./IERC1820Implementer.sol";
/**
* @dev Implementation of the {IERC1820Implementer} interface.
*
* Contracts may inherit from this and call {_registerInterfaceForAddress} to
* declare their willingness to be implementers.
* {IERC1820Registry-setInterfaceImplementer} should then be called for the
* registration to be complete.
*
* CAUTION: This file is deprecated as of v4.9 and will be removed in the next major release.
*/
contract ERC1820Implementer is IERC1820Implementer {
bytes32 private constant _ERC1820_ACCEPT_MAGIC = keccak256("ERC1820_ACCEPT_MAGIC");
mapping(bytes32 => mapping(address => bool)) private _supportedInterfaces;
/**
* @dev See {IERC1820Implementer-canImplementInterfaceForAddress}.
*/
function canImplementInterfaceForAddress(
bytes32 interfaceHash,
address account
) public view virtual override returns (bytes32) {
return _supportedInterfaces[interfaceHash][account] ? _ERC1820_ACCEPT_MAGIC : bytes32(0x00);
}
/**
* @dev Declares the contract as willing to be an implementer of
* `interfaceHash` for `account`.
*
* See {IERC1820Registry-setInterfaceImplementer} and
* {IERC1820Registry-interfaceHash}.
*/
function _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal virtual {
_supportedInterfaces[interfaceHash][account] = true;
}
}

@ -1,20 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC1820Implementer.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface for an ERC1820 implementer, as defined in the
* https://eips.ethereum.org/EIPS/eip-1820#interface-implementation-erc1820implementerinterface[EIP].
* Used by contracts that will be registered as implementers in the
* {IERC1820Registry}.
*/
interface IERC1820Implementer {
/**
* @dev Returns a special value (`ERC1820_ACCEPT_MAGIC`) if this contract
* implements `interfaceHash` for `account`.
*
* See {IERC1820Registry-setInterfaceImplementer}.
*/
function canImplementInterfaceForAddress(bytes32 interfaceHash, address account) external view returns (bytes32);
}

@ -1,112 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/introspection/IERC1820Registry.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the global ERC1820 Registry, as defined in the
* https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
* implementers for interfaces in this registry, as well as query support.
*
* Implementers may be shared by multiple accounts, and can also implement more
* than a single interface for each account. Contracts can implement interfaces
* for themselves, but externally-owned accounts (EOA) must delegate this to a
* contract.
*
* {IERC165} interfaces can also be queried via the registry.
*
* For an in-depth explanation and source code analysis, see the EIP text.
*/
interface IERC1820Registry {
event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
event ManagerChanged(address indexed account, address indexed newManager);
/**
* @dev Sets `newManager` as the manager for `account`. A manager of an
* account is able to set interface implementers for it.
*
* By default, each account is its own manager. Passing a value of `0x0` in
* `newManager` will reset the manager to this initial state.
*
* Emits a {ManagerChanged} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
*/
function setManager(address account, address newManager) external;
/**
* @dev Returns the manager for `account`.
*
* See {setManager}.
*/
function getManager(address account) external view returns (address);
/**
* @dev Sets the `implementer` contract as ``account``'s implementer for
* `interfaceHash`.
*
* `account` being the zero address is an alias for the caller's address.
* The zero address can also be used in `implementer` to remove an old one.
*
* See {interfaceHash} to learn how these are created.
*
* Emits an {InterfaceImplementerSet} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
* - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
* end in 28 zeroes).
* - `implementer` must implement {IERC1820Implementer} and return true when
* queried for support, unless `implementer` is the caller. See
* {IERC1820Implementer-canImplementInterfaceForAddress}.
*/
function setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer) external;
/**
* @dev Returns the implementer of `interfaceHash` for `account`. If no such
* implementer is registered, returns the zero address.
*
* If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
* zeroes), `account` will be queried for support of it.
*
* `account` being the zero address is an alias for the caller's address.
*/
function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);
/**
* @dev Returns the interface hash for an `interfaceName`, as defined in the
* corresponding
* https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
*/
function interfaceHash(string calldata interfaceName) external pure returns (bytes32);
/**
* @notice Updates the cache with whether the contract implements an ERC165 interface or not.
* @param account Address of the contract for which to update the cache.
* @param interfaceId ERC165 interface for which to update the cache.
*/
function updateERC165Cache(address account, bytes4 interfaceId) external;
/**
* @notice Checks whether a contract implements an ERC165 interface or not.
* If the result is not cached a direct lookup on the contract address is performed.
* If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
* {updateERC165Cache} with the contract address.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);
/**
* @notice Checks whether a contract implements an ERC165 interface or not without using or updating the cache.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
}

@ -13,6 +13,72 @@ library Math {
Zero // Toward zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v5.0._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v5.0._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v5.0._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v5.0._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v5.0._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/

@ -15,9 +15,6 @@ pragma solidity ^0.8.0;
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**

@ -1,215 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}

@ -1,68 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SignedSafeMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler
* now has built in overflow checking.
*/
library SignedSafeMath {
/**
* @dev Returns the multiplication of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
return a * b;
}
/**
* @dev Returns the integer division of two signed integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
return a / b;
}
/**
* @dev Returns the subtraction of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
return a - b;
}
/**
* @dev Returns the addition of two signed integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
return a + b;
}
}

@ -140,22 +140,6 @@ library EnumerableMap {
return value;
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToBytes32Map storage map,
bytes32 key,
string memory errorMessage
) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), errorMessage);
return value;
}
/**
* @dev Return the an array containing all the keys
*
@ -242,16 +226,6 @@ library EnumerableMap {
return uint256(get(map._inner, bytes32(key)));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(UintToUintMap storage map, uint256 key, string memory errorMessage) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key), errorMessage));
}
/**
* @dev Return the an array containing all the keys
*
@ -346,20 +320,6 @@ library EnumerableMap {
return address(uint160(uint256(get(map._inner, bytes32(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
UintToAddressMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
}
/**
* @dev Return the an array containing all the keys
*
@ -454,20 +414,6 @@ library EnumerableMap {
return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
AddressToUintMap storage map,
address key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
}
/**
* @dev Return the an array containing all the keys
*
@ -562,20 +508,6 @@ library EnumerableMap {
return uint256(get(map._inner, key));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToUintMap storage map,
bytes32 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, key, errorMessage));
}
/**
* @dev Return the an array containing all the keys
*

@ -1,41 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (vendor/amb/IAMB.sol)
pragma solidity ^0.8.0;
interface IAMB {
event UserRequestForAffirmation(bytes32 indexed messageId, bytes encodedData);
event UserRequestForSignature(bytes32 indexed messageId, bytes encodedData);
event AffirmationCompleted(
address indexed sender,
address indexed executor,
bytes32 indexed messageId,
bool status
);
event RelayedMessage(address indexed sender, address indexed executor, bytes32 indexed messageId, bool status);
function messageSender() external view returns (address);
function maxGasPerTx() external view returns (uint256);
function transactionHash() external view returns (bytes32);
function messageId() external view returns (bytes32);
function messageSourceChainId() external view returns (bytes32);
function messageCallStatus(bytes32 _messageId) external view returns (bool);
function failedMessageDataHash(bytes32 _messageId) external view returns (bytes32);
function failedMessageReceiver(bytes32 _messageId) external view returns (address);
function failedMessageSender(bytes32 _messageId) external view returns (address);
function requireToPassMessage(address _contract, bytes calldata _data, uint256 _gas) external returns (bytes32);
function requireToConfirmMessage(address _contract, bytes calldata _data, uint256 _gas) external returns (bytes32);
function sourceChainId() external view returns (uint256);
function destinationChainId() external view returns (uint256);
}

@ -1,134 +0,0 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (vendor/arbitrum/IArbSys.sol)
pragma solidity >=0.4.21 <0.9.0;
/**
* @title System level functionality
* @notice For use by contracts to interact with core L2-specific functionality.
* Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064.
*/
interface IArbSys {
/**
* @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)
* @return block number as int
*/
function arbBlockNumber() external view returns (uint256);
/**
* @notice Get Arbitrum block hash (reverts unless currentBlockNum-256 <= arbBlockNum < currentBlockNum)
* @return block hash
*/
function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32);
/**
* @notice Gets the rollup's unique chain identifier
* @return Chain identifier as int
*/
function arbChainID() external view returns (uint256);
/**
* @notice Get internal version number identifying an ArbOS build
* @return version number as int
*/
function arbOSVersion() external view returns (uint256);
/**
* @notice Returns 0 since Nitro has no concept of storage gas
* @return uint 0
*/
function getStorageGasAvailable() external view returns (uint256);
/**
* @notice (deprecated) check if current call is top level (meaning it was triggered by an EoA or a L1 contract)
* @dev this call has been deprecated and may be removed in a future release
* @return true if current execution frame is not a call by another L2 contract
*/
function isTopLevelCall() external view returns (bool);
/**
* @notice map L1 sender contract address to its L2 alias
* @param sender sender address
* @param unused argument no longer used
* @return aliased sender address
*/
function mapL1SenderContractAddressToL2Alias(address sender, address unused) external pure returns (address);
/**
* @notice check if the caller (of this caller of this) is an aliased L1 contract address
* @return true iff the caller's address is an alias for an L1 contract address
*/
function wasMyCallersAddressAliased() external view returns (bool);
/**
* @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing
* @return address of the caller's caller, without applying L1 contract address aliasing
*/
function myCallersAddressWithoutAliasing() external view returns (address);
/**
* @notice Send given amount of Eth to dest from sender.
* This is a convenience function, which is equivalent to calling sendTxToL1 with empty data.
* @param destination recipient address on L1
* @return unique identifier for this L2-to-L1 transaction.
*/
function withdrawEth(address destination) external payable returns (uint256);
/**
* @notice Send a transaction to L1
* @dev it is not possible to execute on the L1 any L2-to-L1 transaction which contains data
* to a contract address without any code (as enforced by the Bridge contract).
* @param destination recipient address on L1
* @param data (optional) calldata for L1 contract call
* @return a unique identifier for this L2-to-L1 transaction.
*/
function sendTxToL1(address destination, bytes calldata data) external payable returns (uint256);
/**
* @notice Get send Merkle tree state
* @return size number of sends in the history
* @return root root hash of the send history
* @return partials hashes of partial subtrees in the send history tree
*/
function sendMerkleTreeState() external view returns (uint256 size, bytes32 root, bytes32[] memory partials);
/**
* @notice creates a send txn from L2 to L1
* @param position = (level << 192) + leaf = (0 << 192) + leaf = leaf
*/
event L2ToL1Tx(
address caller,
address indexed destination,
uint256 indexed hash,
uint256 indexed position,
uint256 arbBlockNum,
uint256 ethBlockNum,
uint256 timestamp,
uint256 callvalue,
bytes data
);
/// @dev DEPRECATED in favour of the new L2ToL1Tx event above after the nitro upgrade
event L2ToL1Transaction(
address caller,
address indexed destination,
uint256 indexed uniqueId,
uint256 indexed batchNumber,
uint256 indexInBatch,
uint256 arbBlockNum,
uint256 ethBlockNum,
uint256 timestamp,
uint256 callvalue,
bytes data
);
/**
* @notice logs a merkle branch for proof synthesis
* @param reserved an index meant only to align the 4th index with L2ToL1Transaction's 4th event
* @param hash the merkle hash
* @param position = (level << 192) + leaf
*/
event SendMerkleUpdate(uint256 indexed reserved, bytes32 indexed hash, uint256 indexed position);
}

@ -1,102 +0,0 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (vendor/arbitrum/IBridge.sol)
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
interface IBridge {
event MessageDelivered(
uint256 indexed messageIndex,
bytes32 indexed beforeInboxAcc,
address inbox,
uint8 kind,
address sender,
bytes32 messageDataHash,
uint256 baseFeeL1,
uint64 timestamp
);
event BridgeCallTriggered(address indexed outbox, address indexed to, uint256 value, bytes data);
event InboxToggle(address indexed inbox, bool enabled);
event OutboxToggle(address indexed outbox, bool enabled);
event SequencerInboxUpdated(address newSequencerInbox);
function allowedDelayedInboxList(uint256) external returns (address);
function allowedOutboxList(uint256) external returns (address);
/// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
function delayedInboxAccs(uint256) external view returns (bytes32);
/// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
function sequencerInboxAccs(uint256) external view returns (bytes32);
// OpenZeppelin: changed return type from IOwnable
function rollup() external view returns (address);
function sequencerInbox() external view returns (address);
function activeOutbox() external view returns (address);
function allowedDelayedInboxes(address inbox) external view returns (bool);
function allowedOutboxes(address outbox) external view returns (bool);
function sequencerReportedSubMessageCount() external view returns (uint256);
/**
* @dev Enqueue a message in the delayed inbox accumulator.
* These messages are later sequenced in the SequencerInbox, either
* by the sequencer as part of a normal batch, or by force inclusion.
*/
function enqueueDelayedMessage(
uint8 kind,
address sender,
bytes32 messageDataHash
) external payable returns (uint256);
function executeCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool success, bytes memory returnData);
function delayedMessageCount() external view returns (uint256);
function sequencerMessageCount() external view returns (uint256);
// ---------- onlySequencerInbox functions ----------
function enqueueSequencerMessage(
bytes32 dataHash,
uint256 afterDelayedMessagesRead,
uint256 prevMessageCount,
uint256 newMessageCount
) external returns (uint256 seqMessageIndex, bytes32 beforeAcc, bytes32 delayedAcc, bytes32 acc);
/**
* @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type
* This is done through a separate function entrypoint instead of allowing the sequencer inbox
* to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
* every delayed inbox or every sequencer inbox call.
*/
function submitBatchSpendingReport(address batchPoster, bytes32 dataHash) external returns (uint256 msgNum);
// ---------- onlyRollupOrOwner functions ----------
function setSequencerInbox(address _sequencerInbox) external;
function setDelayedInbox(address inbox, bool enabled) external;
function setOutbox(address inbox, bool enabled) external;
// ---------- initializer ----------
// OpenZeppelin: changed rollup_ type from IOwnable
function initialize(address rollup_) external;
}

@ -1,16 +0,0 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (vendor/arbitrum/IDelayedMessageProvider.sol)
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
interface IDelayedMessageProvider {
/// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
event InboxMessageDelivered(uint256 indexed messageNum, bytes data);
/// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
/// same as InboxMessageDelivered but the batch data is available in tx.input
event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
}

@ -1,152 +0,0 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (vendor/arbitrum/IInbox.sol)
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IBridge.sol";
import "./IDelayedMessageProvider.sol";
interface IInbox is IDelayedMessageProvider {
function bridge() external view returns (IBridge);
// OpenZeppelin: changed return type from ISequencerInbox
function sequencerInbox() external view returns (address);
/**
* @notice Send a generic L2 message to the chain
* @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input
* @param messageData Data of the message being sent
*/
function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256);
/**
* @notice Send a generic L2 message to the chain
* @dev This method can be used to send any type of message that doesn't require L1 validation
* @param messageData Data of the message being sent
*/
function sendL2Message(bytes calldata messageData) external returns (uint256);
function sendL1FundedUnsignedTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
bytes calldata data
) external payable returns (uint256);
function sendL1FundedContractTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
address to,
bytes calldata data
) external payable returns (uint256);
function sendUnsignedTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
uint256 value,
bytes calldata data
) external returns (uint256);
function sendContractTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
address to,
uint256 value,
bytes calldata data
) external returns (uint256);
/**
* @notice Get the L1 fee for submitting a retryable
* @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
* @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
* @param dataLength The length of the retryable's calldata, in bytes
* @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used
*/
function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) external view returns (uint256);
/**
* @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract
* @dev This does not trigger the fallback function when receiving in the L2 side.
* Look into retryable tickets if you are interested in this functionality.
* @dev This function should not be called inside contract constructors
*/
function depositEth() external payable returns (uint256);
/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev all msg.value will deposited to callValueRefundAddress on L2
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
* @param to destination L2 contract address
* @param l2CallValue call value for retryable L2 message
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param data ABI encoded data of L2 message
* @return unique message number of the retryable transaction
*/
function createRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes calldata data
) external payable returns (uint256);
/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds
* come from the deposit alone, rather than falling back on the user's L2 balance
* @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).
* createRetryableTicket method is the recommended standard.
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
* @param to destination L2 contract address
* @param l2CallValue call value for retryable L2 message
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param data ABI encoded data of L2 message
* @return unique message number of the retryable transaction
*/
function unsafeCreateRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes calldata data
) external payable returns (uint256);
// ---------- onlyRollupOrOwner functions ----------
/// @notice pauses all inbox functionality
function pause() external;
/// @notice unpauses all inbox functionality
function unpause() external;
// ---------- initializer ----------
/**
* @dev function to be called one time during the inbox upgrade process
* this is used to fix the storage slots
*/
function postUpgradeInit(IBridge _bridge) external;
// OpenZeppelin: changed _sequencerInbox type from ISequencerInbox
function initialize(IBridge _bridge, address _sequencerInbox) external;
}

@ -1,117 +0,0 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// OpenZeppelin Contracts (last updated v4.8.0) (vendor/arbitrum/IOutbox.sol)
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IBridge.sol";
interface IOutbox {
event SendRootUpdated(bytes32 indexed blockHash, bytes32 indexed outputRoot);
event OutBoxTransactionExecuted(
address indexed to,
address indexed l2Sender,
uint256 indexed zero,
uint256 transactionIndex
);
function rollup() external view returns (address); // the rollup contract
function bridge() external view returns (IBridge); // the bridge contract
function spent(uint256) external view returns (bytes32); // packed spent bitmap
function roots(bytes32) external view returns (bytes32); // maps root hashes => L2 block hash
// solhint-disable-next-line func-name-mixedcase
function OUTBOX_VERSION() external view returns (uint128); // the outbox version
function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external;
/// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
/// When the return value is zero, that means this is a system message
/// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
function l2ToL1Sender() external view returns (address);
/// @return l2Block return L2 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
function l2ToL1Block() external view returns (uint256);
/// @return l1Block return L1 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
function l2ToL1EthBlock() external view returns (uint256);
/// @return timestamp return L2 timestamp when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
function l2ToL1Timestamp() external view returns (uint256);
/// @return outputId returns the unique output identifier of the L2 to L1 tx or 0 if no L2 to L1 transaction is active
function l2ToL1OutputId() external view returns (bytes32);
/**
* @notice Executes a messages in an Outbox entry.
* @dev Reverts if dispute period hasn't expired, since the outbox entry
* is only created once the rollup confirms the respective assertion.
* @dev it is not possible to execute any L2-to-L1 transaction which contains data
* to a contract address without any code (as enforced by the Bridge contract).
* @param proof Merkle proof of message inclusion in send root
* @param index Merkle path to message
* @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
* @param to destination address for L1 contract call
* @param l2Block l2 block number at which sendTxToL1 call was made
* @param l1Block l1 block number at which sendTxToL1 call was made
* @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
* @param value wei in L1 message
* @param data abi-encoded L1 message data
*/
function executeTransaction(
bytes32[] calldata proof,
uint256 index,
address l2Sender,
address to,
uint256 l2Block,
uint256 l1Block,
uint256 l2Timestamp,
uint256 value,
bytes calldata data
) external;
/**
* @dev function used to simulate the result of a particular function call from the outbox
* it is useful for things such as gas estimates. This function includes all costs except for
* proof validation (which can be considered offchain as a somewhat of a fixed cost - it's
* not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation).
* We can't include the cost of proof validation since this is intended to be used to simulate txs
* that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend
* to confirm a pending merkle root, but that would be less practical for integrating with tooling.
* It is only possible to trigger it when the msg sender is address zero, which should be impossible
* unless under simulation in an eth_call or eth_estimateGas
*/
function executeTransactionSimulation(
uint256 index,
address l2Sender,
address to,
uint256 l2Block,
uint256 l1Block,
uint256 l2Timestamp,
uint256 value,
bytes calldata data
) external;
/**
* @param index Merkle path to message
* @return true if the message has been spent
*/
function isSpent(uint256 index) external view returns (bool);
function calculateItemHash(
address l2Sender,
address to,
uint256 l2Block,
uint256 l1Block,
uint256 l2Timestamp,
uint256 value,
bytes calldata data
) external pure returns (bytes32);
function calculateMerkleRoot(bytes32[] memory proof, uint256 path, bytes32 item) external pure returns (bytes32);
}

@ -1,34 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (vendor/optimism/ICrossDomainMessenger.sol)
pragma solidity >0.5.0 <0.9.0;
/**
* @title ICrossDomainMessenger
*/
interface ICrossDomainMessenger {
/**********
* Events *
**********/
event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit);
event RelayedMessage(bytes32 indexed msgHash);
event FailedRelayedMessage(bytes32 indexed msgHash);
/*************
* Variables *
*************/
function xDomainMessageSender() external view returns (address);
/********************
* Public Functions *
********************/
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(address _target, bytes calldata _message, uint32 _gasLimit) external;
}

@ -1,22 +0,0 @@
(The MIT License)
Copyright 2020-2021 Optimism
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -1,7 +0,0 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (vendor/polygon/IFxMessageProcessor.sol)
pragma solidity ^0.8.0;
interface IFxMessageProcessor {
function processMessageFromRoot(uint256 stateId, address rootMessageSender, bytes calldata data) external;
}

@ -11,14 +11,11 @@
** xref:erc20.adoc[ERC20]
*** xref:erc20-supply.adoc[Creating Supply]
** xref:erc721.adoc[ERC721]
** xref:erc777.adoc[ERC777]
** xref:erc1155.adoc[ERC1155]
** xref:erc4626.adoc[ERC4626]
* xref:governance.adoc[Governance]
* xref:crosschain.adoc[Crosschain]
* xref:utilities.adoc[Utilities]
* xref:subgraphs::index.adoc[Subgraphs]

@ -1,210 +0,0 @@
= Adding cross-chain support to contracts
If your contract is targeting to be used in the context of multichain operations, you may need specific tools to identify and process these cross-chain operations.
OpenZeppelin provides the xref:api:crosschain.adoc#CrossChainEnabled[`CrossChainEnabled`] abstract contract, that includes dedicated internal functions.
In this guide, we will go through an example use case: _how to build an upgradeable & mintable ERC20 token controlled by a governor present on a foreign chain_.
== Starting point, our ERC20 contract
Let's start with a small ERC20 contract, that we bootstrapped using the https://wizard.openzeppelin.com/[OpenZeppelin Contracts Wizard], and extended with an owner that has the ability to mint. Note that for demonstration purposes we have not used the built-in `Ownable` contract.
[source,solidity]
----
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyToken is Initializable, ERC20Upgradeable, UUPSUpgradeable {
address public owner;
modifier onlyOwner() {
require(owner == _msgSender(), "Not authorized");
_;
}
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() initializer {}
function initialize(address initialOwner) initializer public {
__ERC20_init("MyToken", "MTK");
__UUPSUpgradeable_init();
owner = initialOwner;
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {
}
}
----
This token is mintable and upgradeable by the owner of the contract.
== Preparing our contract for cross-chain operations.
Let's now imagine that this contract is going to live on one chain, but we want the minting and the upgrading to be performed by a xref:governance.adoc[`governor`] contract on another chain.
For example, we could have our token on xDai, with our governor on mainnet, or we could have our token on mainnet, with our governor on optimism
In order to do that, we will start by adding xref:api:crosschain.adoc#CrossChainEnabled[`CrossChainEnabled`] to our contract. You will notice that the contract is now abstract. This is because `CrossChainEnabled` is an abstract contract: it is not tied to any particular chain and it deals with cross-chain interactions in an abstract way. This is what enables us to easily reuse the code for different chains. We will specialize it later by inheriting from a chain-specific implementation of the abstraction.
```diff
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
+import "@openzeppelin/contracts-upgradeable/crosschain/CrossChainEnabled.sol";
-contract MyToken is Initializable, ERC20Upgradeable, UUPSUpgradeable {
+abstract contract MyTokenCrossChain is Initializable, ERC20Upgradeable, UUPSUpgradeable, CrossChainEnabled {
```
Once that is done, we can use the `onlyCrossChainSender` modifier, provided by `CrossChainEnabled` in order to protect the minting and upgrading operations.
```diff
- function mint(address to, uint256 amount) public onlyOwner {
+ function mint(address to, uint256 amount) public onlyCrossChainSender(owner) {
- function _authorizeUpgrade(address newImplementation) internal override onlyOwner {
+ function _authorizeUpgrade(address newImplementation) internal override onlyCrossChainSender(owner) {
```
This change will effectively restrict the mint and upgrade operations to the `owner` on the remote chain.
== Specializing for a specific chain
Once the abstract cross-chain version of our token is ready we can easily specialize it for the chain we want, or more precisely for the bridge system that we want to rely on.
This is done using one of the many `CrossChainEnabled` implementations.
For example, if our token is on xDai, and our governor on mainnet, we can use the https://docs.tokenbridge.net/amb-bridge/about-amb-bridge[AMB] bridge available on xDai at https://blockscout.com/xdai/mainnet/address/0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59[0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59]
[source,solidity]
----
[...]
import "@openzeppelin/contracts-upgradeable/crosschain/amb/CrossChainEnabledAMB.sol";
contract MyTokenXDAI is
MyTokenCrossChain,
CrossChainEnabledAMB(0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59)
{}
----
If the token is on Ethereum mainnet, and our governor on Optimism, we use the Optimism https://community.optimism.io/docs/protocol/protocol-2.0/#l1crossdomainmessenger[CrossDomainMessenger] available on mainnet at https://etherscan.io/address/0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1[0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1].
[source,solidity]
----
[...]
import "@openzeppelin/contracts-upgradeable/crosschain/optimismCrossChainEnabledOptimism.sol";
contract MyTokenOptimism is
MyTokenCrossChain,
CrossChainEnabledOptimism(0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1)
{}
----
== Mixing cross domain addresses is dangerous
When designing a contract with cross-chain support, it is essential to understand possible fallbacks and the security assumption that are being made.
In this guide, we are particularly focusing on restricting access to a specific caller. This is usually done (as shown above) using `msg.sender` or `_msgSender()`. However, when going cross-chain, it is not just that simple. Even without considering possible bridge issues, it is important to keep in mind that the same address can correspond to very different entities when considering a multi-chain space. EOA wallets can only execute operations if the wallet's private-key signs the transaction. To our knowledge this is the case in all EVM chains, so a cross-chain message coming from such a wallet is arguably equivalent to a non-cross-chain message by the same wallet. The situation is however very different for smart contracts.
Due to the way smart contract addresses are computed, and the fact that smart contracts on different chains live independent lives, you could have two very different contracts live at the same address on different chains. You could imagine two multisig wallets with different signers using the same address on different chains. You could also see a very basic smart wallet live on one chain at the same address as a full-fledged governor on another chain. Therefore, you should be careful that whenever you give permissions to a specific address, you control with chain this address can act from.
== Going further with access control
In the previous example, we have both an `onlyOwner()` modifier and the `onlyCrossChainSender(owner)` mechanism. We didn't use the xref:access-control.adoc#ownership-and-ownable[`Ownable`] pattern because the ownership transfer mechanism in includes is not designed to work with the owner being a cross-chain entity. Unlike xref:access-control.adoc#ownership-and-ownable[`Ownable`], xref:access-control.adoc#role-based-access-control[`AccessControl`] is more effective at capturing the nuances and can effectively be used to build cross-chain-aware contracts.
Using xref:api:access.adoc#AccessControlCrossChain[`AccessControlCrossChain`] includes both the xref:api:access.adoc#AccessControl[`AccessControl`] core and the xref:api:crosschain.adoc#CrossChainEnabled[`CrossChainEnabled`] abstraction. It also includes some binding to make role management compatible with cross-chain operations.
In the case of the `mint` function, the caller must have the `MINTER_ROLE` when the call originates from the same chain. If the caller is on a remote chain, then the caller should not have the `MINTER_ROLE`, but the "aliased" version (`MINTER_ROLE ^ CROSSCHAIN_ALIAS`). This mitigates the danger described in the previous section by strictly separating local accounts from remote accounts from a different chain. See the xref:api:access.adoc#AccessControlCrossChain[`AccessControlCrossChain`] documentation for more details.
```diff
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
+import "@openzeppelin/contracts-upgradeable/access/AccessControlCrossChainUpgradeable.sol";
-abstract contract MyTokenCrossChain is Initializable, ERC20Upgradeable, UUPSUpgradeable, CrossChainEnabled {
+abstract contract MyTokenCrossChain is Initializable, ERC20Upgradeable, UUPSUpgradeable, AccessControlCrossChainUpgradeable {
- address public owner;
- modifier onlyOwner() {
- require(owner == _msgSender(), "Not authorized");
- _;
- }
+ bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
+ bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");
function initialize(address initialOwner) initializer public {
__ERC20_init("MyToken", "MTK");
__UUPSUpgradeable_init();
+ __AccessControl_init();
+ _grantRole(_crossChainRoleAlias(DEFAULT_ADMIN_ROLE), initialOwner); // initialOwner is on a remote chain
- owner = initialOwner;
}
- function mint(address to, uint256 amount) public onlyCrossChainSender(owner) {
+ function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
- function _authorizeUpgrade(address newImplementation) internal override onlyCrossChainSender(owner) {
+ function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADER_ROLE) {
```
This results in the following, final, code:
[source,solidity]
----
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlCrossChainUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
abstract contract MyTokenCrossChain is Initializable, ERC20Upgradeable, AccessControlCrossChainUpgradeable, UUPSUpgradeable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() initializer {}
function initialize(address initialOwner) initializer public {
__ERC20_init("MyToken", "MTK");
__AccessControl_init();
__UUPSUpgradeable_init();
_grantRole(_crossChainRoleAlias(DEFAULT_ADMIN_ROLE), initialOwner); // initialOwner is on a remote chain
}
function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
_mint(to, amount);
}
function _authorizeUpgrade(address newImplementation) internal onlyRole(UPGRADER_ROLE) override {
}
}
import "@openzeppelin/contracts-upgradeable/crosschain/amb/CrossChainEnabledAMB.sol";
contract MyTokenXDAI is
MyTokenCrossChain,
CrossChainEnabledAMB(0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59)
{}
import "@openzeppelin/contracts-upgradeable/crosschain/optimismCrossChainEnabledOptimism.sol";
contract MyTokenOptimism is
MyTokenCrossChain,
CrossChainEnabledOptimism(0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1)
{}
----

@ -2,7 +2,7 @@
ERC1155 is a novel token standard that aims to take the best from previous standards to create a xref:tokens.adoc#different-kinds-of-tokens[*fungibility-agnostic*] and *gas-efficient* xref:tokens.adoc#but_first_coffee_a_primer_on_token_contracts[token contract].
TIP: ERC1155 draws ideas from all of xref:erc20.adoc[ERC20], xref:erc721.adoc[ERC721], and xref:erc777.adoc[ERC777]. If you're unfamiliar with those standards, head to their guides before moving on.
TIP: ERC1155 draws ideas from all of xref:erc20.adoc[ERC20], xref:erc721.adoc[ERC721], and https://eips.ethereum.org/EIPS/eip-777[ERC777]. If you're unfamiliar with those standards, head to their guides before moving on.
[[multi-token-standard]]
== Multi Token Standard
@ -22,9 +22,9 @@ In the spirit of the standard, we've also included batch operations in the non-s
== Constructing an ERC1155 Token Contract
We'll use ERC1155 to track multiple items in our game, which will each have their own unique attributes. We mint all items to the deployer of the contract, which we can later transfer to players. Players are free to keep their tokens or trade them with other people as they see fit, as they would any other asset on the blockchain!
We'll use ERC1155 to track multiple items in our game, which will each have their own unique attributes. We mint all items to the deployer of the contract, which we can later transfer to players. Players are free to keep their tokens or trade them with other people as they see fit, as they would any other asset on the blockchain!
For simplicity, we will mint all items in the constructor, but you could add minting functionality to the contract to mint on demand to players.
For simplicity, we will mint all items in the constructor, but you could add minting functionality to the contract to mint on demand to players.
TIP: For an overview of minting mechanisms, check out xref:erc20-supply.adoc[Creating ERC20 Supply].
@ -112,7 +112,7 @@ The JSON document for token ID 2 might look something like:
For more information about the metadata JSON Schema, check out the https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md#erc-1155-metadata-uri-json-schema[ERC-1155 Metadata URI JSON Schema].
NOTE: You'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game!
NOTE: You'll notice that the item's information is included in the metadata, but that information isn't on-chain! So a game developer could change the underlying metadata, changing the rules of the game!
TIP: If you'd like to put all item information on-chain, you can extend ERC721 to do so (though it will be rather costly) by providing a xref:utilities.adoc#base64[`Base64`] Data URI with the JSON schema encoded. You could also leverage IPFS to store the URI information, but these techniques are out of the scope of this overview guide

@ -1,75 +0,0 @@
= ERC777
CAUTION: As of v4.9, OpenZeppelin's implementation of ERC-777 is deprecated and will be removed in the next major release.
Like xref:erc20.adoc[ERC20], ERC777 is a standard for xref:tokens.adoc#different-kinds-of-tokens[_fungible_ tokens], and is focused around allowing more complex interactions when trading tokens. More generally, it brings tokens and Ether closer together by providing the equivalent of a `msg.value` field, but for tokens.
The standard also brings multiple quality-of-life improvements, such as getting rid of the confusion around `decimals`, minting and burning with proper events, among others, but its killer feature is *receive hooks*. A hook is simply a function in a contract that is called when tokens are sent to it, meaning *accounts and contracts can react to receiving tokens*.
This enables a lot of interesting use cases, including atomic purchases using tokens (no need to do `approve` and `transferFrom` in two separate transactions), rejecting reception of tokens (by reverting on the hook call), redirecting the received tokens to other addresses (similarly to how xref:api:payment#PaymentSplitter[`PaymentSplitter`] does it), among many others.
Furthermore, since contracts are required to implement these hooks in order to receive tokens, _no tokens can get stuck in a contract that is unaware of the ERC777 protocol_, as has happened countless times when using ERC20s.
== What If I Already Use ERC20?
The standard has you covered! The ERC777 standard is *backwards compatible with ERC20*, meaning you can interact with these tokens as if they were ERC20, using the standard functions, while still getting all of the niceties, including send hooks. See the https://eips.ethereum.org/EIPS/eip-777#backward-compatibility[EIP's Backwards Compatibility section] to learn more.
== Constructing an ERC777 Token Contract
We will replicate the `GLD` example of the xref:erc20.adoc#constructing-an-erc20-token-contract[ERC20 guide], this time using ERC777. As always, check out the xref:api:token/ERC777.adoc[`API reference`] to learn more about the details of each function.
[source,solidity]
----
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC777/ERC777.sol";
contract GLDToken is ERC777 {
constructor(uint256 initialSupply, address[] memory defaultOperators)
ERC777("Gold", "GLD", defaultOperators)
{
_mint(msg.sender, initialSupply, "", "");
}
}
----
In this case, we'll be extending from the xref:api:token/ERC777.adoc#ERC777[`ERC777`] contract, which provides an implementation with compatibility support for ERC20. The API is quite similar to that of xref:api:token/ERC777.adoc#ERC777[`ERC777`], and we'll once again make use of xref:api:token/ERC777.adoc#ERC777-_mint-address-address-uint256-bytes-bytes-[`_mint`] to assign the `initialSupply` to the deployer account. Unlike xref:api:token/ERC20.adoc#ERC20-_mint-address-uint256-[ERC20's `_mint`], this one includes some extra parameters, but you can safely ignore those for now.
You'll notice both xref:api:token/ERC777.adoc#IERC777-name--[`name`] and xref:api:token/ERC777.adoc#IERC777-symbol--[`symbol`] are assigned, but not xref:api:token/ERC777.adoc#ERC777-decimals--[`decimals`]. The ERC777 specification makes it mandatory to include support for these functions (unlike ERC20, where it is optional and we had to include xref:api:token/ERC20.adoc#ERC20Detailed[`ERC20Detailed`]), but also mandates that `decimals` always returns a fixed value of `18`, so there's no need to set it ourselves. For a review of ``decimals``'s role and importance, refer back to our xref:erc20.adoc#a-note-on-decimals[ERC20 guide].
Finally, we'll need to set the xref:api:token/ERC777.adoc#IERC777-defaultOperators--[`defaultOperators`]: special accounts (usually other smart contracts) that will be able to transfer tokens on behalf of their holders. If you're not planning on using operators in your token, you can simply pass an empty array. _Stay tuned for an upcoming in-depth guide on ERC777 operators!_
That's it for a basic token contract! We can now deploy it, and use the same xref:api:token/ERC777.adoc#IERC777-balanceOf-address-[`balanceOf`] method to query the deployer's balance:
[source,javascript]
----
> GLDToken.balanceOf(deployerAddress)
1000
----
To move tokens from one account to another, we can use both xref:api:token/ERC777.adoc#ERC777-transfer-address-uint256-[``ERC20``'s `transfer`] method, or the new xref:api:token/ERC777.adoc#ERC777-send-address-uint256-bytes-[``ERC777``'s `send`], which fulfills a very similar role, but adds an optional `data` field:
[source,javascript]
----
> GLDToken.transfer(otherAddress, 300)
> GLDToken.send(otherAddress, 300, "")
> GLDToken.balanceOf(otherAddress)
600
> GLDToken.balanceOf(deployerAddress)
400
----
== Sending Tokens to Contracts
A key difference when using xref:api:token/ERC777.adoc#ERC777-send-address-uint256-bytes-[`send`] is that token transfers to other contracts may revert with the following message:
[source,text]
----
ERC777: token recipient contract has no implementer for ERC777TokensRecipient
----
This is a good thing! It means that the recipient contract has not registered itself as aware of the ERC777 protocol, so transfers to it are disabled to *prevent tokens from being locked forever*. As an example, https://etherscan.io/token/0xa74476443119A942dE498590Fe1f2454d7D4aC0d?a=0xa74476443119A942dE498590Fe1f2454d7D4aC0d[the Golem contract currently holds over 350k `GNT` tokens], worth multiple tens of thousands of dollars, and lacks methods to get them out of there. This has happened to virtually every ERC20-backed project, usually due to user error.
_An upcoming guide will cover how a contract can register itself as a recipient, send and receive hooks, and other advanced features of ERC777!_

@ -28,5 +28,4 @@ You've probably heard of the ERC20 or ERC721 token standards, and that's why you
* xref:erc20.adoc[ERC20]: the most widespread token standard for fungible assets, albeit somewhat limited by its simplicity.
* xref:erc721.adoc[ERC721]: the de-facto solution for non-fungible tokens, often used for collectibles and games.
* xref:erc777.adoc[ERC777]: a richer standard for fungible tokens, enabling new use cases and building on past learnings. Backwards compatible with ERC20.
* xref:erc1155.adoc[ERC1155]: a novel standard for multi-tokens, allowing for a single contract to represent multiple fungible and non-fungible tokens, along with batched operations for increased gas efficiency.

@ -87,9 +87,7 @@ Easy!
Want to split some payments between multiple people? Maybe you have an app that sends 30% of art purchases to the original creator and 70% of the profits to the current owner; you can build that with xref:api:finance.adoc#PaymentSplitter[`PaymentSplitter`]!
In Solidity, there are some security concerns with blindly sending money to accounts, since it allows them to execute arbitrary code. You can read up on these security concerns in the https://consensys.github.io/smart-contract-best-practices/[Ethereum Smart Contract Best Practices] website. One of the ways to fix reentrancy and stalling problems is, instead of immediately sending Ether to accounts that need it, you can use xref:api:security.adoc#PullPayment[`PullPayment`], which offers an xref:api:security.adoc#PullPayment-_asyncTransfer-address-uint256-[`_asyncTransfer`] function for sending money to something and requesting that they xref:api:security.adoc#PullPayment-withdrawPayments-address-payable-[`withdrawPayments()`] it later.
If you want to Escrow some funds, check out xref:api:utils.adoc#Escrow[`Escrow`] and xref:api:utils.adoc#ConditionalEscrow[`ConditionalEscrow`] for governing the release of some escrowed Ether.
In Solidity, there are some security concerns with blindly sending money to accounts, since it allows them to execute arbitrary code. You can read up on these security concerns in the https://consensys.github.io/smart-contract-best-practices/[Ethereum Smart Contract Best Practices] website.
[[collections]]
== Collections
@ -103,7 +101,7 @@ Want to keep track of some numbers that increment by 1 every time you want anoth
=== Base64
xref:api:utils.adoc#Base64[`Base64`] util allows you to transform `bytes32` data into its Base64 `string` representation.
xref:api:utils.adoc#Base64[`Base64`] util allows you to transform `bytes32` data into its Base64 `string` representation.
This is especially useful for building URL-safe tokenURIs for both xref:api:token/ERC721.adoc#IERC721Metadata-tokenURI-uint256-[`ERC721`] or xref:api:token/ERC1155.adoc#IERC1155MetadataURI-uri-uint256-[`ERC1155`]. This library provides a clever way to serve URL-safe https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs/[Data URI] compliant strings to serve on-chain data structures.
@ -122,7 +120,7 @@ contract My721Token is ERC721 {
using Strings for uint256;
constructor() ERC721("My721Token", "MTK") {}
...
function tokenURI(uint256 tokenId)
@ -140,7 +138,7 @@ contract My721Token is ERC721 {
return string(
abi.encodePacked(
"data:application/json;base64,",
"data:application/json;base64,",
Base64.encode(dataURI)
)
);

@ -93,11 +93,7 @@ module.exports = {
},
exposed: {
initializers: true,
exclude: [
'vendor/**/*',
// Exclude Timers from hardhat-exposed because its overloaded functions are not transformed correctly
'utils/Timers{,Upgradeable}.sol',
],
exclude: ['vendor/**/*'],
},
docgen: require('./docs/config'),
};

@ -1,5 +1,5 @@
const format = require('../format-lines');
const { OPTS, LEGACY_OPTS } = require('./Checkpoints.opts.js');
const { OPTS } = require('./Checkpoints.opts.js');
// TEMPLATE
const header = `\
@ -19,7 +19,7 @@ import "./math/SafeCast.sol";
*/
`;
const types = opts => `\
const template = opts => `\
struct ${opts.historyTypeName} {
${opts.checkpointTypeName}[] ${opts.checkpointFieldName};
}
@ -28,10 +28,7 @@ struct ${opts.checkpointTypeName} {
${opts.keyTypeName} ${opts.keyFieldName};
${opts.valueTypeName} ${opts.valueFieldName};
}
`;
/* eslint-disable max-len */
const operations = opts => `\
/**
* @dev Pushes a (\`key\`, \`value\`) pair into a ${opts.historyTypeName} so that it is stored as the checkpoint.
*
@ -87,77 +84,7 @@ function upperLookupRecent(${opts.historyTypeName} storage self, ${opts.keyTypeN
return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
}
`;
const legacyOperations = opts => `\
/**
* @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
* before it is returned, or zero otherwise. Because the number returned corresponds to that at the end of the
* block, the requested block number must be in the past, excluding the current block.
*/
function getAtBlock(${opts.historyTypeName} storage self, uint256 blockNumber) internal view returns (uint256) {
require(blockNumber < block.number, "Checkpoints: block not yet mined");
uint32 key = SafeCast.toUint32(blockNumber);
uint256 len = self.${opts.checkpointFieldName}.length;
uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
}
/**
* @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one
* before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched
* checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of
* checkpoints.
*/
function getAtProbablyRecentBlock(${opts.historyTypeName} storage self, uint256 blockNumber) internal view returns (uint256) {
require(blockNumber < block.number, "Checkpoints: block not yet mined");
uint32 key = SafeCast.toUint32(blockNumber);
uint256 len = self.${opts.checkpointFieldName}.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self.${opts.checkpointFieldName}, mid)._blockNumber) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
}
/**
* @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block.
*
* Returns previous value and new value.
*/
function push(${opts.historyTypeName} storage self, uint256 value) internal returns (uint256, uint256) {
return _insert(self.${opts.checkpointFieldName}, SafeCast.toUint32(block.number), SafeCast.toUint224(value));
}
/**
* @dev Pushes a value onto a History, by updating the latest value using binary operation \`op\`. The new value will
* be set to \`op(latest, delta)\`.
*
* Returns previous value and new value.
*/
function push(
${opts.historyTypeName} storage self,
function(uint256, uint256) view returns (uint256) op,
uint256 delta
) internal returns (uint256, uint256) {
return push(self, op(latest(self), delta));
}
`;
const common = opts => `\
/**
* @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
*/
@ -299,13 +226,6 @@ function _unsafeAccess(${opts.checkpointTypeName}[] storage self, uint256 pos)
module.exports = format(
header.trimEnd(),
'library Checkpoints {',
[
// Legacy types & functions
types(LEGACY_OPTS),
legacyOperations(LEGACY_OPTS),
common(LEGACY_OPTS),
// New flavors
...OPTS.flatMap(opts => [types(opts), operations(opts), common(opts)]),
],
OPTS.flatMap(opts => template(opts)),
'}',
);

@ -12,11 +12,6 @@ const defaultOpts = size => ({
});
module.exports = {
VALUE_SIZES,
OPTS: VALUE_SIZES.map(size => defaultOpts(size)),
LEGACY_OPTS: {
...defaultOpts(224),
historyTypeName: 'History',
checkpointTypeName: 'Checkpoint',
keyFieldName: '_blockNumber',
},
};

@ -1,6 +1,6 @@
const format = require('../format-lines');
const { capitalize } = require('../../helpers');
const { OPTS, LEGACY_OPTS } = require('./Checkpoints.opts.js');
const { OPTS } = require('./Checkpoints.opts.js');
// TEMPLATE
const header = `\
@ -12,7 +12,7 @@ import "../../contracts/utils/math/SafeCast.sol";
`;
/* eslint-disable max-len */
const common = opts => `\
const template = opts => `\
using Checkpoints for Checkpoints.${opts.historyTypeName};
// Maximum gap between keys used during the fuzzing tests: the \`_prepareKeys\` function with make sure that
@ -52,9 +52,7 @@ function _assertLatestCheckpoint(
assertEq(_key, key);
assertEq(_value, value);
}
`;
const testTrace = opts => `\
// tests
function testPush(
${opts.keyTypeName}[] memory keys,
@ -88,7 +86,7 @@ function testPush(
${opts.keyTypeName} lastKey = keys[keys.length - 1];
if (lastKey > 0) {
pastKey = _bound${capitalize(opts.keyTypeName)}(pastKey, 0, lastKey - 1);
vm.expectRevert();
this.push(pastKey, values[keys.length % values.length]);
}
@ -141,116 +139,8 @@ function testLookup(
}
`;
const testHistory = opts => `\
// tests
function testPush(
${opts.keyTypeName}[] memory keys,
${opts.valueTypeName}[] memory values,
${opts.keyTypeName} pastKey
) public {
vm.assume(values.length > 0 && values.length <= keys.length);
_prepareKeys(keys, _KEY_MAX_GAP);
// initial state
assertEq(_ckpts.length(), 0);
assertEq(_ckpts.latest(), 0);
_assertLatestCheckpoint(false, 0, 0);
uint256 duplicates = 0;
for (uint256 i = 0; i < keys.length; ++i) {
${opts.keyTypeName} key = keys[i];
${opts.valueTypeName} value = values[i % values.length];
if (i > 0 && key == keys[i - 1]) ++duplicates;
// push
vm.roll(key);
_ckpts.push(value);
// check length & latest
assertEq(_ckpts.length(), i + 1 - duplicates);
assertEq(_ckpts.latest(), value);
_assertLatestCheckpoint(true, key, value);
}
// Can't push any key in the past
if (keys.length > 0) {
${opts.keyTypeName} lastKey = keys[keys.length - 1];
if (lastKey > 0) {
pastKey = _bound${capitalize(opts.keyTypeName)}(pastKey, 0, lastKey - 1);
vm.roll(pastKey);
vm.expectRevert();
this.push(values[keys.length % values.length]);
}
}
}
// used to test reverts
function push(${opts.valueTypeName} value) external {
_ckpts.push(value);
}
function testLookup(
${opts.keyTypeName}[] memory keys,
${opts.valueTypeName}[] memory values,
${opts.keyTypeName} lookup
) public {
vm.assume(keys.length > 0);
vm.assume(values.length > 0 && values.length <= keys.length);
_prepareKeys(keys, _KEY_MAX_GAP);
${opts.keyTypeName} lastKey = keys[keys.length - 1];
vm.assume(lastKey > 0);
lookup = _bound${capitalize(opts.keyTypeName)}(lookup, 0, lastKey - 1);
${opts.valueTypeName} upper = 0;
for (uint256 i = 0; i < keys.length; ++i) {
${opts.keyTypeName} key = keys[i];
${opts.valueTypeName} value = values[i % values.length];
// push
vm.roll(key);
_ckpts.push(value);
// track expected result of lookups
if (key <= lookup) {
upper = value;
}
}
// check lookup
assertEq(_ckpts.getAtBlock(lookup), upper);
assertEq(_ckpts.getAtProbablyRecentBlock(lookup), upper);
vm.expectRevert(); this.getAtBlock(lastKey);
vm.expectRevert(); this.getAtBlock(lastKey + 1);
vm.expectRevert(); this.getAtProbablyRecentBlock(lastKey);
vm.expectRevert(); this.getAtProbablyRecentBlock(lastKey + 1);
}
// used to test reverts
function getAtBlock(${opts.keyTypeName} key) external view {
_ckpts.getAtBlock(key);
}
// used to test reverts
function getAtProbablyRecentBlock(${opts.keyTypeName} key) external view {
_ckpts.getAtProbablyRecentBlock(key);
}
`;
/* eslint-enable max-len */
// GENERATE
module.exports = format(
header,
// HISTORY
`contract Checkpoints${LEGACY_OPTS.historyTypeName}Test is Test {`,
[common(LEGACY_OPTS), testHistory(LEGACY_OPTS)],
'}',
// TRACEXXX
...OPTS.flatMap(opts => [
`contract Checkpoints${opts.historyTypeName}Test is Test {`,
[common(opts), testTrace(opts)],
'}',
]),
...OPTS.flatMap(opts => [`contract Checkpoints${opts.historyTypeName}Test is Test {`, [template(opts)], '}']),
);

@ -153,22 +153,6 @@ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns
return value;
}
/**
* @dev Same as {get}, with a custom error message when \`key\` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToBytes32Map storage map,
bytes32 key,
string memory errorMessage
) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), errorMessage);
return value;
}
/**
* @dev Return the an array containing all the keys
*
@ -261,20 +245,6 @@ function get(${name} storage map, ${keyType} key) internal view returns (${value
return ${fromBytes32(valueType, `get(map._inner, ${toBytes32(keyType, 'key')})`)};
}
/**
* @dev Same as {get}, with a custom error message when \`key\` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
${name} storage map,
${keyType} key,
string memory errorMessage
) internal view returns (${valueType}) {
return ${fromBytes32(valueType, `get(map._inner, ${toBytes32(keyType, 'key')}, errorMessage)`)};
}
/**
* @dev Return the an array containing all the keys
*

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save