// Sources flattened with hardhat v2.5.0 https://hardhat.org
// File @openzeppelin/contracts/token/ERC20/IERC20.sol@v4.1.0
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File contracts/insured-bridge/interfaces/BridgePoolInterface.sol
pragma solidity ^0.8.0;
interface BridgePoolInterface {
function l1Token() external view returns (IERC20);
function changeAdmin(address newAdmin) external;
}
// File contracts/insured-bridge/interfaces/BridgeAdminInterface.sol
pragma solidity ^0.8.0;
/**
* @notice Helper view methods designed to be called by BridgePool contracts.
*/
interface BridgeAdminInterface {
event SetDepositContracts(
uint256 indexed chainId,
address indexed l2DepositContract,
address indexed l2MessengerContract
);
event SetCrossDomainAdmin(uint256 indexed chainId, address indexed newAdmin);
event SetRelayIdentifier(bytes32 indexed identifier);
event SetOptimisticOracleLiveness(uint32 indexed liveness);
event SetProposerBondPct(uint64 indexed proposerBondPct);
event WhitelistToken(uint256 chainId, address indexed l1Token, address indexed l2Token, address indexed bridgePool);
event SetMinimumBridgingDelay(uint256 indexed chainId, uint64 newMinimumBridgingDelay);
event DepositsEnabled(uint256 indexed chainId, address indexed l2Token, bool depositsEnabled);
event BridgePoolsAdminTransferred(address[] bridgePools, address indexed newAdmin);
function finder() external view returns (address);
struct DepositUtilityContracts {
address depositContract; // L2 deposit contract where cross-chain relays originate.
address messengerContract; // L1 helper contract that can send a message to the L2 with the mapped network ID.
}
function depositContracts(uint256) external view returns (DepositUtilityContracts memory);
struct L1TokenRelationships {
mapping(uint256 => address) l2Tokens; // L2 Chain Id to l2Token address.
address bridgePool;
}
function whitelistedTokens(address, uint256) external view returns (address l2Token, address bridgePool);
function optimisticOracleLiveness() external view returns (uint32);
function proposerBondPct() external view returns (uint64);
function identifier() external view returns (bytes32);
}
// File contracts/insured-bridge/interfaces/MessengerInterface.sol
pragma solidity ^0.8.0;
/**
* @notice Sends cross chain messages to contracts on a specific L2 network. The `relayMessage` implementation will
* differ for each L2.
*/
interface MessengerInterface {
function relayMessage(
address target,
address userToRefund,
uint256 l1CallValue,
uint256 gasLimit,
uint256 gasPrice,
uint256 maxSubmissionCost,
bytes memory message
) external payable;
}
// File contracts/oracle/interfaces/IdentifierWhitelistInterface.sol
pragma solidity ^0.8.0;
/**
* @title Interface for whitelists of supported identifiers that the oracle can provide prices for.
*/
interface IdentifierWhitelistInterface {
/**
* @notice Adds the provided identifier as a supported identifier.
* @dev Price requests using this identifier will succeed after this call.
* @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
*/
function addSupportedIdentifier(bytes32 identifier) external;
/**
* @notice Removes the identifier from the whitelist.
* @dev Price requests using this identifier will no longer succeed after this call.
* @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
*/
function removeSupportedIdentifier(bytes32 identifier) external;
/**
* @notice Checks whether an identifier is on the whitelist.
* @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
* @return bool if the identifier is supported (or not).
*/
function isIdentifierSupported(bytes32 identifier) external view returns (bool);
}
// File contracts/oracle/interfaces/FinderInterface.sol
pragma solidity ^0.8.0;
/**
* @title Provides addresses of the live contracts implementing certain interfaces.
* @dev Examples are the Oracle or Store interfaces.
*/
interface FinderInterface {
/**
* @notice Updates the address of the contract that implements `interfaceName`.
* @param interfaceName bytes32 encoding of the interface name that is either changed or registered.
* @param implementationAddress address of the deployed contract that implements the interface.
*/
function changeImplementationAddress(bytes32 interfaceName, address implementationAddress) external;
/**
* @notice Gets the address of the contract that implements the given `interfaceName`.
* @param interfaceName queried interface.
* @return implementationAddress address of the deployed contract that implements the interface.
*/
function getImplementationAddress(bytes32 interfaceName) external view returns (address);
}
// File contracts/oracle/implementation/Constants.sol
pragma solidity ^0.8.0;
/**
* @title Stores common interface names used throughout the DVM by registration in the Finder.
*/
library OracleInterfaces {
bytes32 public constant Oracle = "Oracle";
bytes32 public constant IdentifierWhitelist = "IdentifierWhitelist";
bytes32 public constant Store = "Store";
bytes32 public constant FinancialContractsAdmin = "FinancialContractsAdmin";
bytes32 public constant Registry = "Registry";
bytes32 public constant CollateralWhitelist = "CollateralWhitelist";
bytes32 public constant OptimisticOracle = "OptimisticOracle";
bytes32 public constant Bridge = "Bridge";
bytes32 public constant GenericHandler = "GenericHandler";
bytes32 public constant SkinnyOptimisticOracle = "SkinnyOptimisticOracle";
}
// File contracts/common/interfaces/AddressWhitelistInterface.sol
pragma solidity ^0.8.0;
interface AddressWhitelistInterface {
function addToWhitelist(address newElement) external;
function removeFromWhitelist(address newElement) external;
function isOnWhitelist(address newElement) external view returns (bool);
function getWhitelist() external view returns (address[] memory);
}
// File contracts/common/implementation/Lockable.sol
pragma solidity ^0.8.0;
/**
* @title A contract that provides modifiers to prevent reentrancy to state-changing and view-only methods. This contract
* is inspired by https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol
* and https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol.
*/
contract Lockable {
bool private _notEntered;
constructor() {
// Storing an initial non-zero value makes deployment a bit more expensive, but in exchange the refund on every
// call to nonReentrant will be lower in amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to increase the likelihood of the full
// refund coming into effect.
_notEntered = true;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant` function is not supported. It is possible to
* prevent this from happening by making the `nonReentrant` function external, and making it call a `private`
* function that does the actual state modification.
*/
modifier nonReentrant() {
_preEntranceCheck();
_preEntranceSet();
_;
_postEntranceReset();
}
/**
* @dev Designed to prevent a view-only method from being re-entered during a call to a `nonReentrant()` state-changing method.
*/
modifier nonReentrantView() {
_preEntranceCheck();
_;
}
// Internal methods are used to avoid copying the require statement's bytecode to every `nonReentrant()` method.
// On entry into a function, `_preEntranceCheck()` should always be called to check if the function is being
// re-entered. Then, if the function modifies state, it should call `_postEntranceSet()`, perform its logic, and
// then call `_postEntranceReset()`.
// View-only methods can simply call `_preEntranceCheck()` to make sure that it is not being re-entered.
function _preEntranceCheck() internal view {
// On the first call to nonReentrant, _notEntered will be true
require(_notEntered, "ReentrancyGuard: reentrant call");
}
function _preEntranceSet() internal {
// Any calls to nonReentrant after this point will fail
_notEntered = false;
}
function _postEntranceReset() internal {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_notEntered = true;
}
}
// File @openzeppelin/contracts/utils/Context.sol@v4.1.0
pragma solidity ^0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// File @openzeppelin/contracts/access/Ownable.sol@v4.1.0
pragma solidity ^0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
// File contracts/insured-bridge/BridgeAdmin.sol
pragma solidity ^0.8.0;
/**
* @notice Administrative contract deployed on L1 that has implicit references to all L2 DepositBoxes.
* @dev This contract is
* responsible for making global variables accessible to BridgePool contracts, which house passive liquidity and
* enable relaying of L2 deposits.
* @dev The owner of this contract can also call permissioned functions on registered L2 DepositBoxes.
*/
contract BridgeAdmin is BridgeAdminInterface, Ownable, Lockable {
// Finder used to point to latest OptimisticOracle and other DVM contracts.
address public override finder;
// This contract can relay messages to any number of L2 DepositBoxes, one per L2 network, each identified by a
// unique network ID. To relay a message, both the deposit box contract address and a messenger contract address
// need to be stored. The messenger implementation differs for each L2 because L1 --> L2 messaging is non-standard.
// The deposit box contract originate the deposits that can be fulfilled by BridgePool contracts on L1.
mapping(uint256 => DepositUtilityContracts) private _depositContracts;
// L1 token addresses are mapped to their canonical token address on L2 and the BridgePool contract that houses
// relay liquidity for any deposits of the canonical L2 token.
mapping(address => L1TokenRelationships) private _whitelistedTokens;
// Set upon construction and can be reset by Owner.
uint32 public override optimisticOracleLiveness;
uint64 public override proposerBondPct;
bytes32 public override identifier;
// Add this modifier to methods that are expected to bridge messages to a L2 Deposit contract, which
// will cause unexpected behavior if the deposit or messenger helper contract isn't set and valid.
modifier canRelay(uint256 chainId) {
_validateDepositContracts(
_depositContracts[chainId].depositContract,
_depositContracts[chainId].messengerContract
);
_;
}
/**
* @notice Construct the Bridge Admin
* @param _finder DVM finder to find other UMA ecosystem contracts.
* @param _optimisticOracleLiveness Timeout that all bridging actions from L2->L1 must wait for a OptimisticOracle response.
* @param _proposerBondPct Percentage of the bridged amount that a relayer must put up as a bond.
* @param _identifier Identifier used when querying the OO for a cross bridge transfer action.
*/
constructor(
address _finder,
uint32 _optimisticOracleLiveness,
uint64 _proposerBondPct,
bytes32 _identifier
) {
finder = _finder;
require(address(_getCollateralWhitelist()) != address(0), "Invalid finder");
_setOptimisticOracleLiveness(_optimisticOracleLiveness);
_setProposerBondPct(_proposerBondPct);
_setIdentifier(_identifier);
}
/**************************************
* ADMIN FUNCTIONS *
**************************************/
/**
* @notice Sets a price identifier to use for relayed deposits. BridgePools reads the identifier from this contract.
* @dev Can only be called by the current owner.
* @param _identifier New identifier to set.
*/
function setIdentifier(bytes32 _identifier) public onlyOwner nonReentrant() {
_setIdentifier(_identifier);
}
/**
* @notice Sets challenge period for relayed deposits. BridgePools will read this value from this contract.
* @dev Can only be called by the current owner.
* @param liveness New OptimisticOracle liveness period to set for relay price requests.
*/
function setOptimisticOracleLiveness(uint32 liveness) public onlyOwner nonReentrant() {
_setOptimisticOracleLiveness(liveness);
}
/**
* @notice Sets challenge period for relayed deposits. BridgePools will read this value from this contract.
* @dev Can only be called by the current owner.
* @param _proposerBondPct New OptimisticOracle proposer bond % to set for relay price requests. 1e18 = 100%.
*/
function setProposerBondPct(uint64 _proposerBondPct) public onlyOwner nonReentrant() {
_setProposerBondPct(_proposerBondPct);
}
/**
* @notice Associates the L2 deposit and L1 messenger helper addresses with an L2 network ID.
* @dev Only callable by the current owner.
* @param chainId L2 network ID to set addresses for.
* @param depositContract Address of L2 deposit contract.
* @param messengerContract Address of L1 helper contract that relays messages to L2.
*/
function setDepositContract(
uint256 chainId,
address depositContract,
address messengerContract
) public onlyOwner nonReentrant() {
_validateDepositContracts(depositContract, messengerContract);
_depositContracts[chainId].depositContract = depositContract;
_depositContracts[chainId].messengerContract = messengerContract;
emit SetDepositContracts(chainId, depositContract, messengerContract);
}
/**
* @notice Enables the current owner to transfer ownership of a set of owned bridge pools to a new owner.
* @dev Only callable by the current owner.
* @param bridgePools array of bridge pools to transfer ownership.
* @param newAdmin new admin contract to set ownership to.
*/
function transferBridgePoolAdmin(address[] memory bridgePools, address newAdmin) public onlyOwner nonReentrant() {
for (uint8 i = 0; i < bridgePools.length; i++) {
BridgePoolInterface(bridgePools[i]).changeAdmin(newAdmin);
}
emit BridgePoolsAdminTransferred(bridgePools, newAdmin);
}
/**************************************************
* CROSSDOMAIN ADMIN FUNCTIONS *
**************************************************/
/**
* @notice Set new contract as the admin address in the L2 Deposit contract.
* @dev Only callable by the current owner.
* @dev msg.value must equal to l1CallValue.
* @param chainId L2 network ID where Deposit contract is deployed.
* @param admin New admin address to set on L2.
* @param l1CallValue Amount of ETH to include in msg.value. Used to pay for L2 fees, but its exact usage varies
* depending on the L2 network that this contract sends a message to.
* @param l2Gas Gas limit to set for relayed message on L2.
* @param l2GasPrice Gas price bid to set for relayed message on L2.
* @param maxSubmissionCost: Arbitrum only: fee deducted from L2 sender's balance to pay for L2 gas.
*/
function setCrossDomainAdmin(
uint256 chainId,
address admin,
uint256 l1CallValue,
uint256 l2Gas,
uint256 l2GasPrice,
uint256 maxSubmissionCost
) public payable onlyOwner canRelay(chainId) nonReentrant() {
require(admin != address(0), "Admin cannot be zero address");
_relayMessage(
_depositContracts[chainId].messengerContract,
l1CallValue,
_depositContracts[chainId].depositContract,
msg.sender,
l2Gas,
l2GasPrice,
maxSubmissionCost,
abi.encodeWithSignature("setCrossDomainAdmin(address)", admin)
);
emit SetCrossDomainAdmin(chainId, admin);
}
/**
* @notice Sets the minimum time between L2-->L1 token withdrawals in the L2 Deposit contract.
* @dev Only callable by the current owner.
* @dev msg.value must equal to l1CallValue.
* @param chainId L2 network ID where Deposit contract is deployed.
* @param minimumBridgingDelay the new minimum delay.
* @param l1CallValue Amount of ETH to include in msg.value. Used to pay for L2 fees, but its exact usage varies
* depending on the L2 network that this contract sends a message to.
* @param l2Gas Gas limit to set for relayed message on L2.
* @param l2GasPrice Gas price bid to set for relayed message on L2.
* @param maxSubmissionCost: Arbitrum only: fee deducted from L2 sender's balance to pay for L2 gas.
*/
function setMinimumBridgingDelay(
uint256 chainId,
uint64 minimumBridgingDelay,
uint256 l1CallValue,
uint256 l2Gas,
uint256 l2GasPrice,
uint256 maxSubmissionCost
) public payable onlyOwner canRelay(chainId) nonReentrant() {
_relayMessage(
_depositContracts[chainId].messengerContract,
l1CallValue,
_depositContracts[chainId].depositContract,
msg.sender,
l2Gas,
l2GasPrice,
maxSubmissionCost,
abi.encodeWithSignature("setMinimumBridgingDelay(uint64)", minimumBridgingDelay)
);
emit SetMinimumBridgingDelay(chainId, minimumBridgingDelay);
}
/**
* @notice Owner can pause/unpause L2 deposits for a tokens.
* @dev Only callable by Owner of this contract. Will set the same setting in the L2 Deposit contract via the cross
* domain messenger.
* @dev msg.value must equal to l1CallValue.
* @param chainId L2 network ID where Deposit contract is deployed.
* @param l2Token address of L2 token to enable/disable deposits for.
* @param depositsEnabled bool to set if the deposit box should accept/reject deposits.
* @param l1CallValue Amount of ETH to include in msg.value. Used to pay for L2 fees, but its exact usage varies
* depending on the L2 network that this contract sends a message to.
* @param l2Gas Gas limit to set for relayed message on L2.
* @param l2GasPrice Gas price bid to set for relayed message on L2.
* @param maxSubmissionCost: Arbitrum only: fee deducted from L2 sender's balance to pay for L2 gas.
*/
function setEnableDeposits(
uint256 chainId,
address l2Token,
bool depositsEnabled,
uint256 l1CallValue,
uint256 l2Gas,
uint256 l2GasPrice,
uint256 maxSubmissionCost
) public payable onlyOwner canRelay(chainId) nonReentrant() {
_relayMessage(
_depositContracts[chainId].messengerContract,
l1CallValue,
_depositContracts[chainId].depositContract,
msg.sender,
l2Gas,
l2GasPrice,
maxSubmissionCost,
abi.encodeWithSignature("setEnableDeposits(address,bool)", l2Token, depositsEnabled)
);
emit DepositsEnabled(chainId, l2Token, depositsEnabled);
}
/**
* @notice Privileged account can associate a whitelisted token with its linked token address on L2. The linked L2
* token can thereafter be deposited into the Deposit contract on L2 and relayed via the BridgePool contract.
* @dev msg.value must equal to l1CallValue.
* @dev This method is also used to to update the address of the bridgePool within a BridgeDepositBox through the
* re-whitelisting of a previously whitelisted token to update the address of the bridge pool in the deposit box.
* @dev Only callable by Owner of this contract. Also initiates a cross-chain call to the L2 Deposit contract to
* whitelist the token mapping.
* @param chainId L2 network ID where Deposit contract is deployed.
* @param l1Token Address of L1 token that can be used to relay L2 token deposits.
* @param l2Token Address of L2 token whose deposits are fulfilled by `l1Token`.
* @param bridgePool Address of BridgePool which manages liquidity to fulfill L2-->L1 relays.
* @param l1CallValue Amount of ETH to include in msg.value. Used to pay for L2 fees, but its exact usage varies
* depending on the L2 network that this contract sends a message to.
* @param l2Gas Gas limit to set for relayed message on L2.
* @param l2GasPrice Gas price bid to set for relayed message on L2.
* @param maxSubmissionCost: Arbitrum only: fee deducted from L2 sender's balance to pay for L2 gas.
*/
function whitelistToken(
uint256 chainId,
address l1Token,
address l2Token,
address bridgePool,
uint256 l1CallValue,
uint256 l2Gas,
uint256 l2GasPrice,
uint256 maxSubmissionCost
) public payable onlyOwner canRelay(chainId) nonReentrant() {
require(bridgePool != address(0), "BridgePool cannot be zero address");
require(l2Token != address(0), "L2 token cannot be zero address");
require(_getCollateralWhitelist().isOnWhitelist(address(l1Token)), "L1Token token not whitelisted");
require(address(BridgePoolInterface(bridgePool).l1Token()) == l1Token, "Bridge pool has different L1 token");
// Braces to resolve Stack too deep compile error
{
L1TokenRelationships storage l1TokenRelationships = _whitelistedTokens[l1Token];
l1TokenRelationships.l2Tokens[chainId] = l2Token; // Set the L2Token at the index of the chainId.
l1TokenRelationships.bridgePool = bridgePool;
}
_relayMessage(
_depositContracts[chainId].messengerContract,
l1CallValue,
_depositContracts[chainId].depositContract,
msg.sender,
l2Gas,
l2GasPrice,
maxSubmissionCost,
abi.encodeWithSignature("whitelistToken(address,address,address)", l1Token, l2Token, bridgePool)
);
emit WhitelistToken(chainId, l1Token, l2Token, bridgePool);
}
/**************************************
* VIEW FUNCTIONS *
**************************************/
function depositContracts(uint256 chainId) external view override returns (DepositUtilityContracts memory) {
return _depositContracts[chainId];
}
function whitelistedTokens(address l1Token, uint256 chainId)
external
view
override
returns (address l2Token, address bridgePool)
{
return (_whitelistedTokens[l1Token].l2Tokens[chainId], _whitelistedTokens[l1Token].bridgePool);
}
/**************************************
* INTERNAL FUNCTIONS *
**************************************/
function _getIdentifierWhitelist() private view returns (IdentifierWhitelistInterface) {
return
IdentifierWhitelistInterface(
FinderInterface(finder).getImplementationAddress(OracleInterfaces.IdentifierWhitelist)
);
}
function _getCollateralWhitelist() private view returns (AddressWhitelistInterface) {
return
AddressWhitelistInterface(
FinderInterface(finder).getImplementationAddress(OracleInterfaces.CollateralWhitelist)
);
}
function _setIdentifier(bytes32 _identifier) private {
require(_getIdentifierWhitelist().isIdentifierSupported(_identifier), "Identifier not registered");
identifier = _identifier;
emit SetRelayIdentifier(identifier);
}
function _setOptimisticOracleLiveness(uint32 liveness) private {
// The following constraints are copied from a similar function in the OptimisticOracle contract:
// - https://github.com/UMAprotocol/protocol/blob/dd211c4e3825fe007d1161025a34e9901b26031a/packages/core/contracts/oracle/implementation/OptimisticOracle.sol#L621
require(liveness < 5200 weeks, "Liveness too large");
require(liveness > 0, "Liveness cannot be 0");
optimisticOracleLiveness = liveness;
emit SetOptimisticOracleLiveness(optimisticOracleLiveness);
}
function _setProposerBondPct(uint64 _proposerBondPct) private {
proposerBondPct = _proposerBondPct;
emit SetProposerBondPct(proposerBondPct);
}
function _validateDepositContracts(address depositContract, address messengerContract) private pure {
require(
(depositContract != address(0)) && (messengerContract != address(0)),
"Invalid deposit or messenger contract"
);
}
// Send msg.value == l1CallValue to Messenger, which can then use it in any way to execute cross domain message.
function _relayMessage(
address messengerContract,
uint256 l1CallValue,
address target,
address user,
uint256 l2Gas,
uint256 l2GasPrice,
uint256 maxSubmissionCost,
bytes memory message
) private {
require(l1CallValue == msg.value, "Wrong number of ETH sent");
MessengerInterface(messengerContract).relayMessage{ value: l1CallValue }(
target,
user,
l1CallValue,
l2Gas,
l2GasPrice,
maxSubmissionCost,
message
);
}
}
{
"compilationTarget": {
"contracts/BridgeAdmin.sol": "BridgeAdmin"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_finder","type":"address"},{"internalType":"uint32","name":"_optimisticOracleLiveness","type":"uint32"},{"internalType":"uint64","name":"_proposerBondPct","type":"uint64"},{"internalType":"bytes32","name":"_identifier","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"bridgePools","type":"address[]"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"BridgePoolsAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"l2Token","type":"address"},{"indexed":false,"internalType":"bool","name":"depositsEnabled","type":"bool"}],"name":"DepositsEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"SetCrossDomainAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"l2DepositContract","type":"address"},{"indexed":true,"internalType":"address","name":"l2MessengerContract","type":"address"}],"name":"SetDepositContracts","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"newMinimumBridgingDelay","type":"uint64"}],"name":"SetMinimumBridgingDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"liveness","type":"uint32"}],"name":"SetOptimisticOracleLiveness","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"proposerBondPct","type":"uint64"}],"name":"SetProposerBondPct","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"SetRelayIdentifier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"l2Token","type":"address"},{"indexed":true,"internalType":"address","name":"bridgePool","type":"address"}],"name":"WhitelistToken","type":"event"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"depositContracts","outputs":[{"components":[{"internalType":"address","name":"depositContract","type":"address"},{"internalType":"address","name":"messengerContract","type":"address"}],"internalType":"struct BridgeAdminInterface.DepositUtilityContracts","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"identifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optimisticOracleLiveness","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposerBondPct","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint256","name":"l1CallValue","type":"uint256"},{"internalType":"uint256","name":"l2Gas","type":"uint256"},{"internalType":"uint256","name":"l2GasPrice","type":"uint256"},{"internalType":"uint256","name":"maxSubmissionCost","type":"uint256"}],"name":"setCrossDomainAdmin","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"depositContract","type":"address"},{"internalType":"address","name":"messengerContract","type":"address"}],"name":"setDepositContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"l2Token","type":"address"},{"internalType":"bool","name":"depositsEnabled","type":"bool"},{"internalType":"uint256","name":"l1CallValue","type":"uint256"},{"internalType":"uint256","name":"l2Gas","type":"uint256"},{"internalType":"uint256","name":"l2GasPrice","type":"uint256"},{"internalType":"uint256","name":"maxSubmissionCost","type":"uint256"}],"name":"setEnableDeposits","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_identifier","type":"bytes32"}],"name":"setIdentifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint64","name":"minimumBridgingDelay","type":"uint64"},{"internalType":"uint256","name":"l1CallValue","type":"uint256"},{"internalType":"uint256","name":"l2Gas","type":"uint256"},{"internalType":"uint256","name":"l2GasPrice","type":"uint256"},{"internalType":"uint256","name":"maxSubmissionCost","type":"uint256"}],"name":"setMinimumBridgingDelay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"liveness","type":"uint32"}],"name":"setOptimisticOracleLiveness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_proposerBondPct","type":"uint64"}],"name":"setProposerBondPct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"bridgePools","type":"address[]"},{"internalType":"address","name":"newAdmin","type":"address"}],"name":"transferBridgePoolAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"l1Token","type":"address"},{"internalType":"address","name":"l2Token","type":"address"},{"internalType":"address","name":"bridgePool","type":"address"},{"internalType":"uint256","name":"l1CallValue","type":"uint256"},{"internalType":"uint256","name":"l2Gas","type":"uint256"},{"internalType":"uint256","name":"l2GasPrice","type":"uint256"},{"internalType":"uint256","name":"maxSubmissionCost","type":"uint256"}],"name":"whitelistToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"l1Token","type":"address"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"whitelistedTokens","outputs":[{"internalType":"address","name":"l2Token","type":"address"},{"internalType":"address","name":"bridgePool","type":"address"}],"stateMutability":"view","type":"function"}]