-
Notifications
You must be signed in to change notification settings - Fork 3.9k
teleportr: add TeleportrDeposit and TeleportrDisburser contracts #2145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mslipper
merged 12 commits into
ethereum-optimism:develop
from
cfromknecht:teleportr-contracts
Feb 22, 2022
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
80dde9f
feat: add base TeleportrDeposit.sol contract
cfromknecht 9222ed1
feat: make contract variables public, remove getters
cfromknecht fdc3006
feat: remove TeleportDeposit destory method
cfromknecht 60a04f3
feat: inline/simplify receive modifiers
cfromknecht 99532fd
feat: add minDepositAmount to TeleportrDeposit.sol
cfromknecht 3bba6e1
feat: emit depositId in TeleportrDeposit.EtherReceived event
cfromknecht 451064a
feat: make Teleportr contract inherit from Ownable
cfromknecht f639979
feat: add NatSpec comments and tests to TeleportrDeposit
cfromknecht 509348f
feat: add L2 TeleportrDisburser contract
cfromknecht 42c9be9
feat: add missing Initializable contract docs
cfromknecht f123c52
Fix slither warnings
mslipper c7ca41a
Remove .only
mslipper File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
132 changes: 132 additions & 0 deletions
132
packages/contracts/contracts/L1/teleportr/TeleportrDeposit.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity >=0.8.9; | ||
|
|
||
| import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; | ||
|
|
||
| /** | ||
| * @title TeleportrDeposit | ||
| * | ||
| * Shout out to 0xclem for providing the inspiration for this contract: | ||
| * https://github.com/0xclem/teleportr/blob/main/contracts/BridgeDeposit.sol | ||
| */ | ||
| contract TeleportrDeposit is Ownable { | ||
| /// The minimum amount that be deposited in a receive. | ||
| uint256 public minDepositAmount; | ||
| /// The maximum amount that be deposited in a receive. | ||
| uint256 public maxDepositAmount; | ||
| /// The maximum balance the contract can hold after a receive. | ||
| uint256 public maxBalance; | ||
| /// The total number of successful deposits received. | ||
| uint256 public totalDeposits; | ||
|
|
||
| /** | ||
| * @notice Emitted any time the minimum deposit amount is set. | ||
| * @param previousAmount The previous minimum deposit amount. | ||
| * @param newAmount The new minimum deposit amount. | ||
| */ | ||
| event MinDepositAmountSet(uint256 previousAmount, uint256 newAmount); | ||
|
|
||
| /** | ||
| * @notice Emitted any time the maximum deposit amount is set. | ||
| * @param previousAmount The previous maximum deposit amount. | ||
| * @param newAmount The new maximum deposit amount. | ||
| */ | ||
| event MaxDepositAmountSet(uint256 previousAmount, uint256 newAmount); | ||
|
|
||
| /** | ||
| * @notice Emitted any time the contract maximum balance is set. | ||
| * @param previousBalance The previous maximum contract balance. | ||
| * @param newBalance The new maximum contract balance. | ||
| */ | ||
| event MaxBalanceSet(uint256 previousBalance, uint256 newBalance); | ||
|
|
||
| /** | ||
| * @notice Emitted any time the balance is withdrawn by the owner. | ||
| * @param owner The current owner and recipient of the funds. | ||
| * @param balance The current contract balance paid to the owner. | ||
| */ | ||
| event BalanceWithdrawn(address indexed owner, uint256 balance); | ||
|
|
||
| /** | ||
| * @notice Emitted any time a successful deposit is received. | ||
| * @param depositId A unique sequencer number identifying the deposit. | ||
| * @param emitter The sending address of the payer. | ||
| * @param amount The amount deposited by the payer. | ||
| */ | ||
| event EtherReceived(uint256 indexed depositId, address indexed emitter, uint256 indexed amount); | ||
|
|
||
| /** | ||
| * @notice Initializes a new TeleportrDeposit contract. | ||
| * @param _minDepositAmount The initial minimum deposit amount. | ||
| * @param _maxDepositAmount The initial maximum deposit amount. | ||
| * @param _maxBalance The initial maximum contract balance. | ||
| */ | ||
| constructor( | ||
| uint256 _minDepositAmount, | ||
| uint256 _maxDepositAmount, | ||
| uint256 _maxBalance | ||
| ) { | ||
| minDepositAmount = _minDepositAmount; | ||
| maxDepositAmount = _maxDepositAmount; | ||
| maxBalance = _maxBalance; | ||
| totalDeposits = 0; | ||
| emit MinDepositAmountSet(0, _minDepositAmount); | ||
| emit MaxDepositAmountSet(0, _maxDepositAmount); | ||
| emit MaxBalanceSet(0, _maxBalance); | ||
| } | ||
|
|
||
| /** | ||
| * @notice Accepts deposits that will be disbursed to the sender's address on L2. | ||
| * The method reverts if the amount is less than the current | ||
| * minDepositAmount, the amount is greater than the current | ||
| * maxDepositAmount, or the amount causes the contract to exceed its maximum | ||
| * allowed balance. | ||
| */ | ||
| receive() external payable { | ||
| require(msg.value >= minDepositAmount, "Deposit amount is too small"); | ||
| require(msg.value <= maxDepositAmount, "Deposit amount is too big"); | ||
| require(address(this).balance <= maxBalance, "Contract max balance exceeded"); | ||
|
Comment on lines
+86
to
+88
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice, this is much more readable than modifiers IMO. |
||
|
|
||
| emit EtherReceived(totalDeposits, msg.sender, msg.value); | ||
| unchecked { | ||
| totalDeposits += 1; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @notice Sends the contract's current balance to the owner. | ||
| */ | ||
| function withdrawBalance() external onlyOwner { | ||
| address _owner = owner(); | ||
| uint256 _balance = address(this).balance; | ||
| emit BalanceWithdrawn(_owner, _balance); | ||
| payable(_owner).transfer(_balance); | ||
| } | ||
|
|
||
| /** | ||
| * @notice Sets the minimum amount that can be deposited in a receive. | ||
| * @param _minDepositAmount The new minimum deposit amount. | ||
| */ | ||
| function setMinAmount(uint256 _minDepositAmount) external onlyOwner { | ||
| emit MinDepositAmountSet(minDepositAmount, _minDepositAmount); | ||
| minDepositAmount = _minDepositAmount; | ||
| } | ||
|
|
||
| /** | ||
| * @notice Sets the maximum amount that can be deposited in a receive. | ||
| * @param _maxDepositAmount The new maximum deposit amount. | ||
| */ | ||
| function setMaxAmount(uint256 _maxDepositAmount) external onlyOwner { | ||
| emit MaxDepositAmountSet(maxDepositAmount, _maxDepositAmount); | ||
| maxDepositAmount = _maxDepositAmount; | ||
| } | ||
|
|
||
| /** | ||
| * @notice Sets the maximum balance the contract can hold after a receive. | ||
| * @param _maxBalance The new maximum contract balance. | ||
| */ | ||
| function setMaxBalance(uint256 _maxBalance) external onlyOwner { | ||
| emit MaxBalanceSet(maxBalance, _maxBalance); | ||
| maxBalance = _maxBalance; | ||
| } | ||
| } | ||
115 changes: 115 additions & 0 deletions
115
packages/contracts/contracts/L2/teleportr/TeleportrDisburser.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity >=0.8.9; | ||
|
|
||
| import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; | ||
|
|
||
| /** | ||
| * @title TeleportrDisburser | ||
| */ | ||
| contract TeleportrDisburser is Ownable { | ||
| /** | ||
| * @notice A struct holding the address and amount to disbursement. | ||
| */ | ||
| struct Disbursement { | ||
| uint256 amount; | ||
| address addr; | ||
| } | ||
|
|
||
| /// The total number of disbursements processed. | ||
| uint256 public totalDisbursements; | ||
|
|
||
| /** | ||
| * @notice Emitted any time the balance is withdrawn by the owner. | ||
| * @param owner The current owner and recipient of the funds. | ||
| * @param balance The current contract balance paid to the owner. | ||
| */ | ||
| event BalanceWithdrawn(address indexed owner, uint256 balance); | ||
|
|
||
| /** | ||
| * @notice Emitted any time a disbursement is successfuly sent. | ||
| * @param depositId The unique sequence number identifying the deposit. | ||
| * @param to The recipient of the disbursement. | ||
| * @param amount The amount sent to the recipient. | ||
| */ | ||
| event DisbursementSuccess(uint256 indexed depositId, address indexed to, uint256 amount); | ||
|
|
||
| /** | ||
| * @notice Emitted any time a disbursement fails to send. | ||
| * @param depositId The unique sequence number identifying the deposit. | ||
| * @param to The intended recipient of the disbursement. | ||
| * @param amount The amount intended to be sent to the recipient. | ||
| */ | ||
| event DisbursementFailed(uint256 indexed depositId, address indexed to, uint256 amount); | ||
|
|
||
| /** | ||
| * @notice Initializes a new TeleportrDisburser contract. | ||
| */ | ||
| constructor() { | ||
| totalDisbursements = 0; | ||
| } | ||
|
|
||
| /** | ||
| * @notice Accepts a list of Disbursements and forwards the amount paid to | ||
| * the contract to each recipient. The method reverts if there are zero | ||
| * disbursements, the total amount to forward differs from the amount sent | ||
| * in the transaction, or the _nextDepositId is unexpected. Failed | ||
| * disbursements will not cause the method to revert, but will instead be | ||
| * held by the contract and availabe for the owner to withdraw. | ||
| * @param _nextDepositId The depositId of the first Dispursement. | ||
| * @param _disbursements A list of Disbursements to process. | ||
| */ | ||
| function disburse(uint256 _nextDepositId, Disbursement[] calldata _disbursements) | ||
| external | ||
| payable | ||
| onlyOwner | ||
| { | ||
| // Ensure there are disbursements to process. | ||
| uint256 _numDisbursements = _disbursements.length; | ||
| require(_numDisbursements > 0, "No disbursements"); | ||
|
|
||
| // Ensure the _nextDepositId matches our expected value. | ||
| uint256 _depositId = totalDisbursements; | ||
| require(_depositId == _nextDepositId, "Unexpected next deposit id"); | ||
| unchecked { | ||
| totalDisbursements += _numDisbursements; | ||
| } | ||
|
|
||
| // Ensure the amount sent in the transaction is equal to the sum of the | ||
| // disbursements. | ||
| uint256 _totalDisbursed = 0; | ||
| for (uint256 i = 0; i < _numDisbursements; i++) { | ||
| _totalDisbursed += _disbursements[i].amount; | ||
| } | ||
| require(_totalDisbursed == msg.value, "Disbursement total != amount sent"); | ||
|
|
||
| // Process disbursements. | ||
| for (uint256 i = 0; i < _numDisbursements; i++) { | ||
| uint256 _amount = _disbursements[i].amount; | ||
| address _addr = _disbursements[i].addr; | ||
|
|
||
| // Deliver the dispursement amount to the receiver. If the | ||
| // disbursement fails, the amount will be kept by the contract | ||
| // rather than reverting to prevent blocking progress on other | ||
| // disbursements. | ||
|
|
||
| // slither-disable-next-line calls-loop,reentrancy-events | ||
| (bool success, ) = _addr.call{ value: _amount, gas: 2300 }(""); | ||
| if (success) emit DisbursementSuccess(_depositId, _addr, _amount); | ||
| else emit DisbursementFailed(_depositId, _addr, _amount); | ||
|
|
||
| unchecked { | ||
| _depositId += 1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @notice Sends the contract's current balance to the owner. | ||
| */ | ||
| function withdrawBalance() external onlyOwner { | ||
| address _owner = owner(); | ||
| uint256 balance = address(this).balance; | ||
| emit BalanceWithdrawn(_owner, balance); | ||
| payable(_owner).transfer(balance); | ||
| } | ||
| } |
14 changes: 14 additions & 0 deletions
14
packages/contracts/contracts/test-helpers/FailingReceiver.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity >=0.8.9; | ||
|
|
||
| /** | ||
| * @title FailingReceiver | ||
| */ | ||
| contract FailingReceiver { | ||
| /** | ||
| * @notice Receiver that always reverts upon receiving ether. | ||
| */ | ||
| receive() external payable { | ||
| require(false, "FailingReceiver"); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # FailingReceiver | ||
|
|
||
|
|
||
|
|
||
| > FailingReceiver | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI this is a noop. State vars are initialized to zero:
Source: Types — Solidity 0.8.13 documentation