-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(protocol): move prover assignment verification to hook (#15208)
Co-authored-by: Daniel Wang <dong77@gmail.com> Co-authored-by: jeff <113397187+cyberhorsey@users.noreply.github.com> Co-authored-by: David <david@taiko.xyz> Co-authored-by: Roger <50648015+RogerLamTd@users.noreply.github.com> Co-authored-by: adaki2004 <keszeydani@gmail.com> Co-authored-by: D <51912515+adaki2004@users.noreply.github.com> Co-authored-by: Brecht Devos <Brechtp.Devos@gmail.com> Co-authored-by: Jeffery Walsh <cyberhorsey@gmail.com>
- Loading branch information
1 parent
80dd6c4
commit d61af90
Showing
40 changed files
with
331 additions
and
363 deletions.
There are no files selected for viewing
Binary file not shown.
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
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
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
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
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
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
171 changes: 171 additions & 0 deletions
171
packages/protocol/contracts/L1/hooks/AssignmentHook.sol
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,171 @@ | ||
// SPDX-License-Identifier: MIT | ||
// _____ _ _ _ _ | ||
// |_ _|_ _(_) |_____ | | __ _| |__ ___ | ||
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-< | ||
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/ | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol"; | ||
import "../../common/EssentialContract.sol"; | ||
import "../../libs/LibAddress.sol"; | ||
import "../TaikoData.sol"; | ||
import "../TaikoToken.sol"; | ||
import "./IHook.sol"; | ||
|
||
/// @title AssignmentHook | ||
/// A hook that handles prover assignment varification and fee processing. | ||
contract AssignmentHook is EssentialContract, IHook { | ||
using LibAddress for address; | ||
|
||
struct ProverAssignment { | ||
address feeToken; | ||
uint64 expiry; | ||
uint64 maxBlockId; | ||
uint64 maxProposedIn; | ||
bytes32 metaHash; | ||
TaikoData.TierFee[] tierFees; | ||
bytes signature; | ||
} | ||
|
||
struct Input { | ||
ProverAssignment assignment; | ||
uint256 tip; | ||
} | ||
|
||
// Max gas paying the prover. This should be large enough to prevent the | ||
// worst cases, usually block proposer shall be aware the risks and only | ||
// choose provers that cannot consume too much gas when receiving Ether. | ||
uint256 public constant MAX_GAS_PAYING_PROVER = 200_000; | ||
|
||
event BlockAssigned( | ||
address indexed assignedProver, TaikoData.BlockMetadata meta, ProverAssignment assignment | ||
); | ||
|
||
error HOOK_ASSIGNMENT_EXPIRED(); | ||
error HOOK_ASSIGNMENT_INVALID_SIG(); | ||
error HOOK_ASSIGNMENT_INSUFFICIENT_FEE(); | ||
error HOOK_TIER_NOT_FOUND(); | ||
|
||
function init(address _addressManager) external initializer { | ||
EssentialContract._init(_addressManager); | ||
} | ||
|
||
function onBlockProposed( | ||
TaikoData.Block memory blk, | ||
TaikoData.BlockMetadata memory meta, | ||
bytes memory data | ||
) | ||
external | ||
payable | ||
nonReentrant | ||
onlyFromNamed("taiko") | ||
{ | ||
Input memory input = abi.decode(data, (Input)); | ||
ProverAssignment memory assignment = input.assignment; | ||
|
||
// Check assignment validity | ||
if ( | ||
block.timestamp > assignment.expiry | ||
|| assignment.metaHash != 0 && blk.metaHash != assignment.metaHash | ||
|| assignment.maxBlockId != 0 && meta.id > assignment.maxBlockId | ||
|| assignment.maxProposedIn != 0 && block.number > assignment.maxProposedIn | ||
) { | ||
revert HOOK_ASSIGNMENT_EXPIRED(); | ||
} | ||
|
||
// Hash the assignment with the blobHash, this hash will be signed by | ||
// the prover, therefore, we add a string as a prefix. | ||
bytes32 hash = hashAssignment(assignment, msg.sender, meta.blobHash); | ||
|
||
if (!blk.assignedProver.isValidSignature(hash, assignment.signature)) { | ||
revert HOOK_ASSIGNMENT_INVALID_SIG(); | ||
} | ||
|
||
// Send the liveness bond to the Taiko contract | ||
TaikoToken tko = TaikoToken(resolve("taiko_token", false)); | ||
tko.transferFrom(blk.assignedProver, msg.sender, blk.livenessBond); | ||
|
||
// Find the prover fee using the minimal tier | ||
uint256 proverFee = _getProverFee(assignment.tierFees, meta.minTier); | ||
|
||
// The proposer irrevocably pays a fee to the assigned prover, either in | ||
// Ether or ERC20 tokens. | ||
uint256 refund; | ||
if (assignment.feeToken == address(0)) { | ||
if (msg.value < proverFee + input.tip) { | ||
revert HOOK_ASSIGNMENT_INSUFFICIENT_FEE(); | ||
} | ||
|
||
unchecked { | ||
refund = msg.value - proverFee - input.tip; | ||
} | ||
|
||
// Paying Ether | ||
blk.assignedProver.sendEther(proverFee, MAX_GAS_PAYING_PROVER); | ||
} else { | ||
if (msg.value < input.tip) { | ||
revert HOOK_ASSIGNMENT_INSUFFICIENT_FEE(); | ||
} | ||
unchecked { | ||
refund = msg.value - input.tip; | ||
} | ||
// Paying ERC20 tokens | ||
ERC20Upgradeable(assignment.feeToken).transferFrom( | ||
msg.sender, blk.assignedProver, proverFee | ||
); | ||
} | ||
|
||
// block.coinbase can be address(0) in tests | ||
if (input.tip != 0 && block.coinbase != address(0)) { | ||
address(block.coinbase).sendEther(input.tip); | ||
} | ||
|
||
if (refund != 0) { | ||
msg.sender.sendEther(refund); | ||
} | ||
|
||
emit BlockAssigned(blk.assignedProver, meta, assignment); | ||
} | ||
|
||
function hashAssignment( | ||
ProverAssignment memory assignment, | ||
address taikoAddress, | ||
bytes32 blobHash | ||
) | ||
public | ||
pure | ||
returns (bytes32) | ||
{ | ||
return keccak256( | ||
abi.encode( | ||
"PROVER_ASSIGNMENT", | ||
taikoAddress, | ||
blobHash, | ||
assignment.feeToken, | ||
assignment.expiry, | ||
assignment.maxBlockId, | ||
assignment.maxProposedIn, | ||
assignment.tierFees | ||
) | ||
); | ||
} | ||
|
||
function _getProverFee( | ||
TaikoData.TierFee[] memory tierFees, | ||
uint16 tierId | ||
) | ||
private | ||
pure | ||
returns (uint256) | ||
{ | ||
for (uint256 i; i < tierFees.length; ++i) { | ||
if (tierFees[i].tier == tierId) return tierFees[i].fee; | ||
} | ||
revert HOOK_TIER_NOT_FOUND(); | ||
} | ||
} | ||
|
||
/// @title ProxiedAssignmentHook | ||
/// @notice Proxied version of the parent contract. | ||
contract ProxiedAssignmentHook is Proxied, AssignmentHook { } |
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,20 @@ | ||
// SPDX-License-Identifier: MIT | ||
// _____ _ _ _ _ | ||
// |_ _|_ _(_) |_____ | | __ _| |__ ___ | ||
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-< | ||
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/ | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import "../TaikoData.sol"; | ||
|
||
/// @title IHook Interface | ||
interface IHook { | ||
function onBlockProposed( | ||
TaikoData.Block memory blk, | ||
TaikoData.BlockMetadata memory meta, | ||
bytes memory data | ||
) | ||
external | ||
payable; | ||
} |
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
Oops, something went wrong.