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
parent
8de6eba8a3
commit
0f10efe232
@ -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. |
@ -1,45 +0,0 @@ |
||||
// SPDX-License-Identifier: MIT |
||||
// OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControlCrossChain.sol) |
||||
|
||||
pragma solidity ^0.8.4; |
||||
|
||||
import "./AccessControl.sol"; |
||||
import "../crosschain/CrossChainEnabled.sol"; |
||||
|
||||
/** |
||||
* @dev An extension to {AccessControl} with support for cross-chain access management. |
||||
* For each role, is extension implements an equivalent "aliased" role that is used for |
||||
* restricting calls originating from other chains. |
||||
* |
||||
* For example, if a function `myFunction` is protected by `onlyRole(SOME_ROLE)`, and |
||||
* if an address `x` has role `SOME_ROLE`, it would be able to call `myFunction` directly. |
||||
* A wallet or contract at the same address on another chain would however not be able |
||||
* to call this function. In order to do so, it would require to have the role |
||||
* `_crossChainRoleAlias(SOME_ROLE)`. |
||||
* |
||||
* This aliasing is required to protect against multiple contracts living at the same |
||||
* address on different chains but controlled by conflicting entities. |
||||
* |
||||
* _Available since v4.6._ |
||||
*/ |
||||
abstract contract AccessControlCrossChain is AccessControl, CrossChainEnabled { |
||||
bytes32 public constant CROSSCHAIN_ALIAS = keccak256("CROSSCHAIN_ALIAS"); |
||||
|
||||
/** |
||||
* @dev See {AccessControl-_checkRole}. |
||||
*/ |
||||
function _checkRole(bytes32 role) internal view virtual override { |
||||
if (_isCrossChain()) { |
||||
_checkRole(_crossChainRoleAlias(role), _crossChainSender()); |
||||
} else { |
||||
super._checkRole(role); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @dev Returns the aliased role corresponding to `role`. |
||||
*/ |
||||
function _crossChainRoleAlias(bytes32 role) internal pure virtual returns (bytes32) { |
||||
return role ^ CROSSCHAIN_ALIAS; |
||||
} |
||||
} |
@ -1,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; |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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) {} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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"; |
@ -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}} |
@ -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; |
||||
} |
||||
} |
@ -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); |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
@ -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) |
||||
{} |
||||
---- |
@ -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!_ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue