-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bold-c4e068b568ff662f49ed191c5c3188ea7b6138b2
- Loading branch information
1 parent
90037b9
commit c3868f1
Showing
40 changed files
with
4,114 additions
and
2,439 deletions.
There are no files selected for viewing
This file contains 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,103 @@ | ||
// Copyright 2021-2022, Offchain Labs, Inc. | ||
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
// | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import "../rollup/IRollupLogic.sol"; | ||
import "../rollup/IRollupCore.sol"; | ||
import "./StakingPoolErrors.sol"; | ||
|
||
/// @notice Staking pool contract for target assertion. | ||
/// Allows users to deposit stake, create assertion once required stake amount is reached, | ||
/// and reclaim their stake when and if the assertion is confirmed. | ||
contract AssertionStakingPool { | ||
using SafeERC20 for IERC20; | ||
address public immutable rollup; | ||
bytes32 public immutable assertionHash; | ||
AssertionInputs public assertionInputs; | ||
IERC20 public immutable stakeToken; | ||
mapping(address => uint256) public depositedTokenBalances; | ||
|
||
event StakeDeposited(address indexed sender, uint256 amount); | ||
event StakeWithdrawn(address indexed sender, uint256 amount); | ||
|
||
/// @param _rollup Rollup contract of target chain | ||
/// @param _assertionInputs Inputs to be passed into Rollup.stakeOnNewAssertion | ||
/// @param _assertionHash Assertion hash to be passed into Rollup.stakeOnNewAssertion | ||
constructor( | ||
address _rollup, | ||
AssertionInputs memory _assertionInputs, | ||
bytes32 _assertionHash | ||
) { | ||
rollup = _rollup; | ||
assertionHash = _assertionHash; | ||
assertionInputs = _assertionInputs; | ||
stakeToken = IERC20(IRollupCore(rollup).stakeToken()); | ||
} | ||
|
||
/// @notice Deposit stake into pool contract. | ||
/// @param _amount amount of stake token to deposit | ||
function depositIntoPool(uint256 _amount) external { | ||
depositedTokenBalances[msg.sender] += _amount; | ||
stakeToken.safeTransferFrom(msg.sender, address(this), _amount); | ||
emit StakeDeposited(msg.sender, _amount); | ||
} | ||
|
||
/// @notice Create assertion. Callable only if required stake has been reached and assertion has not been asserted yet. | ||
function createAssertion() external { | ||
uint256 requiredStake = getRequiredStake(); | ||
// approve spending from rollup for newStakeOnNewAssertion call | ||
stakeToken.safeIncreaseAllowance(rollup, requiredStake); | ||
// reverts if pool doesn't have enough stake and if assertion has already been asserted | ||
IRollupUser(rollup).newStakeOnNewAssertion(requiredStake, assertionInputs, assertionHash); | ||
} | ||
|
||
/// @notice Make stake withdrawable. | ||
/// @dev Separate call from withdrawStakeBackIntoPool since returnOldDeposit reverts with 0 balance (in e.g., case of admin forceRefundStaker) | ||
function makeStakeWithdrawable() public { | ||
// this checks for active staker | ||
IRollupUser(rollup).returnOldDeposit(); | ||
} | ||
|
||
/// @notice Move stake back from rollup contract to this contract. | ||
/// Callable only if this contract has already created an assertion and it's now inactive. | ||
/// @dev Separate call from makeStakeWithdrawable since returnOldDeposit reverts with 0 balance (in e.g., case of admin forceRefundStaker) | ||
function withdrawStakeBackIntoPool() public { | ||
IRollupUser(rollup).withdrawStakerFunds(); | ||
} | ||
|
||
/// @notice Combines makeStakeWithdrawable and withdrawStakeBackIntoPool into single call | ||
function makeStakeWithdrawableAndWithdrawBackIntoPool() external { | ||
makeStakeWithdrawable(); | ||
withdrawStakeBackIntoPool(); | ||
} | ||
|
||
/// @notice Send supplied amount of stake from this contract back to its depositor. | ||
/// @param _amount stake amount to withdraw | ||
function withdrawFromPool(uint256 _amount) public { | ||
uint256 balance = depositedTokenBalances[msg.sender]; | ||
if (balance == 0) { | ||
revert NoBalanceToWithdraw(msg.sender); | ||
} | ||
if (_amount > balance) { | ||
revert AmountExceedsBalance(msg.sender, _amount, balance); | ||
} | ||
depositedTokenBalances[msg.sender] = balance - _amount; | ||
stakeToken.safeTransfer(msg.sender, _amount); | ||
emit StakeWithdrawn(msg.sender, _amount); | ||
} | ||
|
||
/// @notice Send full balance of stake from this contract back to its depositor. | ||
function withdrawFromPool() external { | ||
withdrawFromPool(depositedTokenBalances[msg.sender]); | ||
} | ||
|
||
/// @notice Get required stake for pool's assertion. | ||
/// Requried stake for a given assertion is set in the previous assertion's config data | ||
function getRequiredStake() public view returns (uint256) { | ||
return assertionInputs.beforeStateData.configData.requiredStake; | ||
} | ||
} |
This file contains 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,83 @@ | ||
// Copyright 2021-2022, Offchain Labs, Inc. | ||
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
// | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "./AssertionStakingPool.sol"; | ||
import "@openzeppelin/contracts/utils/Create2.sol"; | ||
import "@openzeppelin/contracts/utils/Address.sol"; | ||
import "./StakingPoolErrors.sol"; | ||
|
||
/// @notice Creates staking pool contract for a target assertion. Can be used for any child Arbitrum chain running on top of the deployed AssertionStakingPoolCreator's chain. | ||
contract AssertionStakingPoolCreator { | ||
event NewAssertionPoolCreated( | ||
address indexed rollup, | ||
bytes32 indexed _assertionHash, | ||
address assertionPool | ||
); | ||
|
||
/// @notice Create a staking pool contract | ||
/// @param _rollup Rollup contract of target chain | ||
/// @param _assertionInputs Inputs to be passed into Rollup.stakeOnNewAssertion | ||
/// @param _assertionHash Assertion hash to be passed into Rollup.stakeOnNewAssertion | ||
function createPoolForAssertion( | ||
address _rollup, | ||
AssertionInputs memory _assertionInputs, | ||
bytes32 _assertionHash | ||
) external returns (address) { | ||
address assertionPoolAddress = address( | ||
new AssertionStakingPool{salt: _getPoolSalt(_rollup, _assertionInputs, _assertionHash)}( | ||
_rollup, | ||
_assertionInputs, | ||
_assertionHash | ||
) | ||
); | ||
|
||
emit NewAssertionPoolCreated(_rollup, _assertionHash, assertionPoolAddress); | ||
return assertionPoolAddress; | ||
} | ||
|
||
/// @notice get staking pool deployed with provided inputs; reverts if pool contract doesn't exist. | ||
/// @param _rollup Rollup contract of target chain | ||
/// @param _assertionInputs Inputs to be passed into Rollup.stakeOnNewAssertion | ||
/// @param _assertionHash Assertion hash to be passed into Rollup.stakeOnNewAssertion | ||
function getPool( | ||
address _rollup, | ||
AssertionInputs memory _assertionInputs, | ||
bytes32 _assertionHash | ||
) public view returns (AssertionStakingPool) { | ||
bytes32 salt = _getPoolSalt(_rollup, _assertionInputs, _assertionHash); | ||
bytes32 bytecodeHash = _getPoolByteCodeHash(_rollup, _assertionInputs, _assertionHash); | ||
|
||
address pool = Create2.computeAddress(salt, bytecodeHash, address(this)); | ||
if (Address.isContract(pool)) { | ||
return AssertionStakingPool(pool); | ||
} else { | ||
revert PoolDoesntExist(_rollup, _assertionInputs, _assertionHash); | ||
} | ||
} | ||
|
||
/// @notice get salt for create2 staking pool deployment | ||
function _getPoolSalt( | ||
address _rollup, | ||
AssertionInputs memory _assertionInputs, | ||
bytes32 _assertionHash | ||
) internal pure returns (bytes32) { | ||
return keccak256(abi.encode(_rollup, _assertionInputs, _assertionHash)); | ||
} | ||
|
||
/// @notice get bytecodehash for create2 staking pool deployment | ||
function _getPoolByteCodeHash( | ||
address _rollup, | ||
AssertionInputs memory _assertionInputs, | ||
bytes32 _assertionHash | ||
) internal pure returns (bytes32) { | ||
bytes memory bytecode = type(AssertionStakingPool).creationCode; | ||
return | ||
keccak256( | ||
abi.encodePacked(bytecode, abi.encode(_rollup, _assertionInputs, _assertionHash)) | ||
); | ||
} | ||
} |
This file contains 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 @@ | ||
// Copyright 2021-2022, Offchain Labs, Inc. | ||
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
// | ||
pragma solidity ^0.8.0; | ||
import "../rollup/IRollupLogic.sol"; | ||
|
||
error NoBalanceToWithdraw(address sender); | ||
|
||
error PoolDoesntExist(address rollup, AssertionInputs assertionInputs, bytes32 assertionHash); | ||
|
||
error AmountExceedsBalance(address sender, uint256 amount, uint256 balance); |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.